module klang.klang.绑定.klang绑定_;
import 全局;
import std.conv: ·to = to;
import std.functional: ·fd = toDelegate;
import std.typecons: ·Tuple = Tuple, ·tuple = tuple;
import ··Klang节点_ = klang.klang.语法节点.Klang节点_;
import ··klang类型_ = klang.klang.类型.klang类型_;
import ··诊断_ = klang.编译.诊断.诊断_;
import klang.编译.类型.枚举值.枚举值_: SK, TK;
import klang.编译.诊断集.诊断集_: 诊断集_;
import klang.编译.诊断.诊断_: 诊断_, 诊断消息_;
import klang.编译.类型.类型_: 基础符号_ = 符号_, 绑定函数_, 绑定子函数_, 清理函数_, 符号表_, 流节点_, 流标志_, 文本范围_, 三元结果_, 程序主机接口_, 编译选项基类_;
import klang.klang.类型.klang类型_: KSK, 符号标志_, 版本容器块种类_, 符号_ = Klang符号_, 节点标志_, 内部符号名_, Klang编译选项_ = 编译选项_, 模块导入位置种类_;
import klang.klang.语法节点.Klang节点_: 节点_ = Klang节点_, 标识符_ = Klang标识符_, Klang源文件_, 修饰符标志_, 修饰符_, 程序声明_, 属性声明_, 方法声明_, 构建声明_, 释放声明_, 函数声明_, 函数类声明_, 属性赋值_, 简洁属性赋值_, 枚举成员_, 导入从成员_, 导入成员_, 形参声明_, 类型形参_, 函数类型_, 函数表达式_, 箭头函数_, 若是子句_, 默认子句_, 变量声明_, 表达式语句_, 如果语句_, 调用表达式_, 测试单元语句_, 导入成员块_, 导入从成员块_, 版本表达式语句_, 版本语句_, 导入版本成员_, 导入从版本成员_, 语句_, 标签语句_, 变量语句_, 当循环语句_, 循环语句_, 循环属于_, 假如语句_, 返回语句_, 抛出语句_, 跳出语句_, 继续语句_, 尝试语句_, 若是块_, 断言语句_, 块_, 若是或默认子句_, 对象声明_, 结构声明_, 接口声明_, 别名声明_, 类型声明_, 枚举声明_, 外部修饰符声明_, 表达式_, 前缀一元表达式_, 后缀一元表达式_, 条件表达式_, 二元表达式_, 类型转换表达式_, 类型断言表达式_, 类型查询表达式_, 开放括号表达式_, 属性访问表达式_, 元素访问表达式_, 符号引用表达式_, 非空表达式_, 接口字面量表达式_, 结构字面量表达式_, 数组字面量表达式_, 动态类字面量表达式_, 表达式列表表达式_, 展开表达式_, 词典键值表达式_, 获取Klang节点, 遍历节点, 是klang节点, 是函数类的, 是函数类声明, 是循环或循环属于语句, 是语句但不是声明, 是函数声明, 是枚举声明, 是新建表达式, 是块, 是属性访问表达式, 是非空表达式, 是元素访问表达式, 是klang文本字面量, 是klang数字字面量, 获取块, 是容器块, 修饰符种类转标志, 是启动或测试启动函数, 是初始函数, 获取源文件;
import klang.编译.语法节点.节点_: 源文件_, 节点数组_, 查找祖先;
import 基础节点 = klang.编译.语法节点.节点_;
import 核心 = klang.编译.核心.核心_;
import klang.编译.核心.核心_: 整数_, 词典_, 去重数组_, 文本转小写, 包含, 过滤, 连接, 循环每个, 开始包含, 创建数组, 克隆词典, 克隆数组, 返回零值, sliceAfter, getRangesWhere;
import klang.编译.工具.工具_: 创建符号表, 创建文件诊断消息;
import klang.klang.工具.klang工具_: 是点的名称, 是赋值目标, 是局部变量声明, setValueDeclaration, 获取立即调用函数表达式, isAssignmentOperator, 获取扩展符号标志;
import klang.编译.路径.路径_: 获取目录路径, 获取基础文件名称, 正规化路径和片段, 路径和路径片段_;
long 符号数量 = 0;
绑定子函数_ 绑定函数;
程序主机接口_ 当前主机;
Klang编译选项_ 编译选项;
dstring[] 包名;
Klang源文件_ file;
基础节点.节点_ container;
基础节点.节点_ blockScopeContainer;
基础节点.节点_ lastContainer;
// state used by control flow analysis
流节点_ currentFlow;
流节点_ currentBreakTarget;
流节点_ currentContinueTarget;
流节点_ currentReturnTarget;
流节点_ currentTrueTarget;
流节点_ currentFalseTarget;
流节点_ currentExceptionTarget;
流节点_ preSwitchCaseFlow;
klang.klang.绑定.klang绑定_.活动标签_[] activeLabels;
基础节点.节点_ 外部容器节点;
基础节点.节点_ 当前程序集节点;
基础节点.节点_ 当前范围容器节点;
外部修饰符声明_ 当前的外部修饰符;
核心.去重数组_!(dstring) 当前版本路径;
核心.词典_!(核心.去重数组_!(dstring)) 文件设置的版本标识符;
符号_ thisSymbol;
符号_ 原型符号;
符号标志_ 声明块符号标志组 = 符号标志_.无_;
符号标志_ 父级标志 = 符号标志_.无_;
long 是内部函数;
bool hasExplicitReturn = false;
流节点_ unreachableFlow;
流节点_ reportedUnreachableFlow;
流节点_ delegate(流节点_) flowNodeCreated;
static this() {
    是内部函数 = -1;
    unreachableFlow = new 流节点_(流标志_.Unreachable);
    reportedUnreachableFlow = new 流节点_(流标志_.Unreachable);
    flowNodeCreated = .获取初始流函数();
}
enum 容器标志_ : int {
    /** 当前节点不是容器，在重新插入该节点之前不应进行任何容器操作。 */
    无_ = 0,
    /** 当前节点是一个容器。 在重新插入它之前，应将其设置为当前容器（和块容器）。 当前节点没有局部变量。 示例：类、对象字面量、类型字面量、接口... */
    是容器_ = 1,
    /** 当前节点是块作用域容器。 在重新插入它之前，应将其设置为当前块容器。 示例：块（当不受函数养育时）、Catch 子句、for/for in/for 语句... */
    是块范围容器_ = 2,
    /** 当前节点是控制流路径的容器。应保存和恢复当前控制流，并在容器内初始化新的控制流。 */
    是控制流容器_ = 4,
    /** 是函数族 */
    是函数类的_ = 8,
    /** 是函数表达式 */
    是函数表达式_ = 16,
    /** 具有本地 */
    有本地组_ = 32,
    /** 是接口 */
    是接口_ = 64,
    是对象_ = 128,
    是结构_ = 256,
    是外部容器_ = 512,
    是范围容器_ = 1024,
    是程序集容器_ = 2048
}
class 活动标签_ {
    标签语句_ node;
    dstring name;
    流节点_ breakTarget;
    流节点_ continueTarget;
    bool referenced;
    this() { }
    this(标签语句_ node, dstring name, 流节点_ breakTarget, 流节点_ continueTarget, bool referenced) {
        this.node = node;
        this.name = name;
        this.breakTarget = breakTarget;
        this.continueTarget = continueTarget;
        this.referenced = referenced;
    }
}
流节点_ initFlowNode(流节点_ n) {
    return n;
}
流节点_ createBranchLabel() {
    return .initFlowNode(new 流节点_(流标志_.BranchLabel));
}
流节点_ createLoopLabel() {
    return .initFlowNode(new 流节点_(流标志_.LoopLabel));
}
流节点_ createReduceLabel(流节点_ target, 流节点_[] antecedents, 流节点_ antecedent) {
    流节点_ n = .initFlowNode(new 流节点_(流标志_.ReduceLabel));
    n.target = target;
    n.antecedents = antecedents;
    n.antecedent = antecedent;
    return n;
}
流节点_ delegate(流节点_) 获取初始流函数() {
    return cast(流节点_ delegate(流节点_))(·fd(&.initFlowNode));
}
容器标志_ 获取容器标志(基础节点.节点_ node) {
    if (node.种类 == SK.源文件) {
        return 容器标志_.是容器_ | 容器标志_.是控制流容器_ | 容器标志_.有本地组_;
    }
    if (!是klang节点(node)) {
        return 容器标志_.无_;
    }
    节点_ n = (cast(节点_)(node));
    switch (n.目标种类) {
        case KSK.枚举声明:
        case KSK.结构字面量表达式:
        case KSK.接口字面量表达式: {
            return 容器标志_.是容器_;
        }
        case KSK.对象声明:
        case KSK.结构声明:
        case KSK.类型声明: {
            return 容器标志_.是容器_ | 容器标志_.是对象_ | 容器标志_.是结构_ | 容器标志_.是范围容器_ | 容器标志_.是外部容器_;
        }
        case KSK.接口声明: {
            return 容器标志_.是容器_ | 容器标志_.是接口_ | 容器标志_.是范围容器_;
        }
        case KSK.别名声明: {
            return 容器标志_.是容器_ | 容器标志_.有本地组_;
        }
        case KSK.程序声明: {
            return 容器标志_.是容器_ | 容器标志_.是控制流容器_ | 容器标志_.是程序集容器_;
        }
        case KSK.源文件: {
            return 容器标志_.是容器_ | 容器标志_.是控制流容器_ | 容器标志_.有本地组_;
        }
        case KSK.测试单元语句: {
            return 容器标志_.是容器_ | 容器标志_.是控制流容器_ | 容器标志_.有本地组_ | 容器标志_.是外部容器_;
        }
        case KSK.构建声明:
        case KSK.方法声明:
        case KSK.函数声明: {
            return 容器标志_.是容器_ | 容器标志_.是控制流容器_ | 容器标志_.有本地组_ | 容器标志_.是函数类的_ | 容器标志_.是外部容器_;
        }
        case KSK.释放声明:
        case KSK.函数类型: {
            return 容器标志_.是容器_ | 容器标志_.是控制流容器_ | 容器标志_.有本地组_ | 容器标志_.是函数类的_;
        }
        case KSK.函数表达式:
        case KSK.箭头函数: {
            return 容器标志_.是容器_ | 容器标志_.是控制流容器_ | 容器标志_.有本地组_ | 容器标志_.是函数类的_ | 容器标志_.是函数表达式_;
        }
        case KSK.属性声明: {
            属性声明_ nn = (cast(属性声明_)(n));
            if (nn.初始化 !is ··null!(节点_)) {
                return 容器标志_.是控制流容器_;
            }
            return 容器标志_.无_;
        }
        case KSK.若是子句: {
            若是子句_ nn = (cast(若是子句_)(n));
            if ((nn.语句组 !is null) && (nn.语句组.原型 !is ··null!(节点_[])) && nn.语句组.length > 0) {
                return 容器标志_.是块范围容器_ | 容器标志_.有本地组_;
            }
            return 容器标志_.无_;
        }
        case KSK.默认子句: {
            默认子句_ nn = (cast(默认子句_)(n));
            if ((nn.语句组 !is null) && (nn.语句组.原型 !is ··null!(节点_[])) && nn.语句组.length > 0) {
                return 容器标志_.是块范围容器_ | 容器标志_.有本地组_;
            }
            return 容器标志_.无_;
        }
        case KSK.捕获子句:
        case KSK.循环语句:
        case KSK.循环属于:
        case KSK.当循环语句:
        case KSK.若是块:
        case KSK.同步语句: {
            return 容器标志_.是块范围容器_ | 容器标志_.有本地组_;
        }
        case KSK.块: {
            基础节点.节点_ pn = n.父节点;
            if (是klang节点(pn)) {
                节点_ kpn = (cast(节点_)(pn));
                容器标志_ 结果 = 是函数类的(kpn) || 是循环或循环属于语句(kpn) || !是容器块(n) ? 容器标志_.无_ : 容器标志_.是块范围容器_;
                if (结果 == 容器标志_.是块范围容器_) {
                    n.标志 |= (cast(ulong)(节点标志_.是容器块));
                }
                return 结果;
            }
            return 容器标志_.无_;
        }
        default: break;
    }
    return 容器标志_.无_;
}
绑定函数_ 创建绑定工作站(绑定子函数_ 绑定, 程序主机接口_ 主机) {
    .绑定函数 = cast(绑定子函数_)(绑定);
    .当前主机 = 主机;
    .编译选项 = (cast(Klang编译选项_)(主机.获取编译选项()));
    .包名 = [编译选项.名称];
    return cast(绑定函数_)(·fd(&.绑定工作站));
}
绑定函数_ 创建绑定子工作站() {
    return cast(绑定函数_)(·fd(&.绑定子工作站));
}
清理函数_ 创建绑定清理() {
    return cast(清理函数_)(·fd(&.绑定清理函数));
}
void 绑定清理函数() {
    .file = 返回零值!(Klang源文件_)();
    .container = 返回零值!(基础节点.节点_)();
    .blockScopeContainer = 返回零值!(基础节点.节点_)();
    .lastContainer = 返回零值!(基础节点.节点_)();
    .currentFlow = 返回零值!(流节点_)();
    .currentBreakTarget = 返回零值!(流节点_)();
    .currentContinueTarget = 返回零值!(流节点_)();
    .currentReturnTarget = 返回零值!(流节点_)();
    .currentTrueTarget = 返回零值!(流节点_)();
    .currentFalseTarget = 返回零值!(流节点_)();
    .currentExceptionTarget = 返回零值!(流节点_)();
    .preSwitchCaseFlow = 返回零值!(流节点_)();
    .activeLabels = 返回零值!(活动标签_[])();
    .hasExplicitReturn = false;
    .外部容器节点 = 返回零值!(基础节点.节点_)();
    .当前程序集节点 = 返回零值!(基础节点.节点_)();
    .当前范围容器节点 = 返回零值!(基础节点.节点_)();
    .当前版本路径 = 返回零值!(核心.去重数组_!(dstring))();
    .当前的外部修饰符 = 返回零值!(外部修饰符声明_)();
    .thisSymbol = 返回零值!(符号_)();
    .原型符号 = 返回零值!(符号_)();
    .声明块符号标志组 = 返回零值!(符号标志_)();
    .父级标志 = 返回零值!(符号标志_)();
    .是内部函数 = -1;
}
void 添加符号声明(符号_ 符号, 节点_ 节点, 符号标志_ 标志) {
    符号.标志 |= (cast(整数_)(标志));
    .追加!(基础节点.节点_)(符号.声明组, 节点);
    节点.符号 = 符号;
    if ((标志 & 符号标志_.值_) != 0) {
        setValueDeclaration(符号, 节点);
    }
    if ((标志 & (符号标志_.有成员_)) != 0) {
        符号.成员 = 创建符号表();
    }
}
符号_ 创建符号(符号标志_ 标志, dstring 名称) {
    符号_ 符号 = new 符号_((cast(整数_)(标志)), 名称);
    ++符号数量;
    return 符号;
}
void 验证外部容器重名(符号_ sym, 符号表_ symt) {
    基础节点.节点_ vdec = sym.值声明;
    if (vdec is ··null!(基础节点.节点_)) {
        return;
    }
    基础节点.节点_ n = vdec.父节点;
    while(n !is ··null!(基础节点.节点_)) {
        符号表_ st;
        if ((n.本地组 !is null) && (n.本地组.原型 !is ··null!(基础符号_[dstring])) && (n.本地组 != symt || n.本地组.原型 != symt.原型)) {
            st = n.本地组;
        }
        else if ((n.符号 !is ··null!(基础符号_)) && (n.符号.成员 != symt || n.符号.成员.原型 != symt.原型)) {
            st = n.符号.成员;
        }
        if ((st is null) || (st.原型 is ··null!(基础符号_[dstring]))) {
            return;
        }
        if (st.具有(sym.名称)) {
            基础符号_ errN = st.获取(sym.名称);
            if ((errN.标志 & (符号标志_.变量_ | 符号标志_.形参声明_)) != 0) {
                .error(vdec, 诊断集_.声明的成员_0_与容器符号名称冲突, sym.名称);
                return;
            }
        }
        if (n.目标种类 == KSK.程序声明 || n.目标种类 == KSK.测试单元语句 || n.目标种类 == KSK.源文件) {
            return;
        }
        n = n.父节点;
    }
}
bool 应该附加前缀(符号标志_ 符号标志) {
    if ((.当前版本路径 !is ··null!(核心.去重数组_!(dstring))) && !当前版本路径.是空的()) {
        return (符号标志 & (符号标志_.对象_ | 符号标志_.接口_ | 符号标志_.结构_ | 符号标志_.类型别名_ | 符号标志_.类型声明_ | 符号标志_.枚举声明_ | 符号标志_.别名_ | 符号标志_.变量_ | 符号标志_.函数_ | 符号标志_.签名_)) != 0 && 当前版本路径.去重排序输出() != ""d;
    }
    return false;
}
符号_ 声明符号(符号表_ 符号表, 节点_ node, dstring name, 符号_ 父符号 = ··null!(符号_), 符号标志_ 符号标志 = ··null!(符号标志_), 符号标志_ 排除标志 = ··null!(符号标志_)) {
    符号_ 符号 = ··null!(符号_);
    dstring 原始名称 = name;
    if (.应该附加前缀(符号标志)) {
        name = 当前版本路径.去重排序输出() ~ "|"d ~ name;
    }
    if (符号表.具有(name)) {
        符号 = (cast(符号_)(符号表.获取(name)));
        if ((符号.标志 & 排除标志) != 0) {
            .error(node, 诊断集_.Duplicate_identifier_0, name);
        }
    }
    else {
        if (原始名称 != "_"d && 开始包含(原始名称, "_"d)) {
            if ((符号标志 & (符号标志_.形参声明_ | 符号标志_.类型形参_ | 符号标志_.局部变量_)) == 0) {
                符号标志 |= 符号标志_.私有_;
            }
        }
        符号 = .创建符号(符号标志, name);
        if (原始名称 != "_"d && !是启动或测试启动函数(node) && !是初始函数(node)) {
            符号表.p·设置(name, 符号);
        }
        else {
            符号.标志 |= (cast(整数_)(符号标志_.不使用_));
        }
    }
    if (.当前的外部修饰符 !is ··null!(外部修饰符声明_)) {
        符号.外部修饰符 = .当前的外部修饰符;
    }
    .添加符号声明(符号, node, 符号标志);
    if (符号.父符号 !is ··null!(基础符号_)) {
        assert(符号.父符号 == 父符号, "符号的父符号不同错误"c);
    }
    else {
        符号.父符号 = 父符号;
    }
    if ((符号标志 & (符号标志_.变量_ | 符号标志_.形参声明_)) != 0) {
        .验证外部容器重名(符号, 符号表);
    }
    return 符号;
}
符号_ 声明符号并添加到符号表(节点_ node, dstring name, 符号标志_ 标志, 符号标志_ 排除) {
    switch (container.目标种类) {
        case KSK.源文件: {
            return .声明符号(file.本地组, node, name, /*parent*/ ··null!(符号_), 标志, 排除);
        }
        case KSK.函数类型:
        case KSK.别名声明:
        case KSK.测试单元语句:
        case KSK.同步语句: {
            return .声明符号(container.本地组, node, name, /*parent*/ ··null!(符号_), 标志, 排除);
        }
        case KSK.方法声明:
        case KSK.构建声明:
        case KSK.释放声明:
        case KSK.函数声明:
        case KSK.函数表达式:
        case KSK.箭头函数: {
            return .声明符号(container.本地组, node, name, (((标志 & 符号标志_.内部声明_) != 0) ? (cast(符号_)(container.符号)) : ··null!(符号_)), 标志, 排除);
        }
        case KSK.接口字面量表达式:
        case KSK.结构字面量表达式:
        case KSK.枚举声明:
        case KSK.接口声明:
        case KSK.程序声明:
        case KSK.对象声明:
        case KSK.结构声明:
        case KSK.类型声明: {
            return .声明符号(container.符号.成员, node, name, (cast(符号_)(container.符号)), 标志, 排除);
        }
        case KSK.块: {
            if ((cast(块_)(.container)).版本容器块种类 != 0) {
                return .声明符号(container.本地组, node, name, /*parent*/ ··null!(符号_), 标志, 排除);
            }
        }
        default: break;
    }
    return ··null!(符号_);
}
void 绑定工作站(基础节点.节点_ node) {
    if (node.种类 == SK.源文件) {
        .file = (cast(Klang源文件_)((cast(源文件_)(node))));
        .文件设置的版本标识符 = .转换为去重数组(file.文件设置的版本标识符);
        return;
    }
    节点_ nn = 获取Klang节点(node);
    if (nn !is ··null!(节点_)) {
        long ksk = nn.目标种类;
        switch (ksk) {
            case KSK.符号引用表达式:
            case KSK.属性访问表达式:
            case KSK.元素访问表达式: {
                if ((.currentFlow !is ··null!(流节点_)) && .是可收窄引用(nn)) {
                    nn.流节点 = .currentFlow;
                }
                break;
            }
            case KSK.本体_: {
                nn.符号 = .thisSymbol;
            }
            case KSK.原型_: {
                nn.符号 = .原型符号;
            }
            case KSK.标识符: {
                if (.currentFlow !is ··null!(流节点_)) {
                    nn.流节点 = .currentFlow;
                }
                break;
            }
            case KSK.程序声明: {
                .绑定程序声明((cast(程序声明_)(nn)));
                break;
            }
            case KSK.变量声明: {
                const auto ···temp·0·_1 = .获取符号标志(nn);
                .声明符号并添加到符号表((cast(节点_)(nn)), .获取名称(nn), ···temp·0·_1[0], ···temp·0·_1[1]);
                break;
            }
            case KSK.属性赋值:
            case KSK.导入从成员:
            case KSK.导入成员:
            case KSK.类型形参:
            case KSK.简洁属性赋值:
            case KSK.属性声明:
            case KSK.运算符签名:
            case KSK.索引签名:
            case KSK.枚举成员:
            case KSK.形参声明: {
                const auto ···temp·0·_2 = .获取符号标志(nn);
                .声明符号并添加到符号表((cast(节点_)(nn)), .获取名称(nn), ···temp·0·_2[0], ···temp·0·_2[1]);
                break;
            }
            case KSK.接口声明:
            case KSK.别名声明:
            case KSK.枚举声明: {
                .父级标志 = 符号标志_.无_;
                const auto ···temp·0·_3 = .获取符号标志(nn);
                .声明符号并添加到符号表((cast(节点_)(nn)), .获取名称(nn), ···temp·0·_3[0], ···temp·0·_3[1]);
                break;
            }
            case KSK.结构声明:
            case KSK.对象声明: {
                .父级标志 = 符号标志_.无_;
                const auto ···temp·0·_4 = .获取符号标志(nn);
                符号_ sym = .声明符号并添加到符号表((cast(节点_)(nn)), .获取名称(nn), ···temp·0·_4[0], ···temp·0·_4[1]);
                if (sym !is ··null!(符号_)) {
                    .thisSymbol = sym;
                }
                break;
            }
            case KSK.类型声明: {
                .父级标志 = 符号标志_.无_;
                const auto ···temp·0·_5 = .获取符号标志(nn);
                符号_ sym = .声明符号并添加到符号表((cast(节点_)(nn)), .获取名称(nn), ···temp·0·_5[0], ···temp·0·_5[1]);
                if (sym !is ··null!(符号_)) {
                    符号_ 符号 = .创建符号(符号标志_.属性_, 内部符号名_.原型_);
                    符号.值声明 = sym.值声明;
                    符号.声明组 = sym.声明组;
                    符号.父符号 = sym;
                    if ((sym.成员 is null) || (sym.成员.原型 is ··null!(基础符号_[dstring]))) {
                        sym.成员 = 创建符号表();
                    }
                    sym.成员.p·设置(内部符号名_.原型_, 符号);
                    .thisSymbol = sym;
                    .原型符号 = 符号;
                }
                break;
            }
            case KSK.构建声明:
            case KSK.释放声明:
            case KSK.方法声明:
            case KSK.函数声明: {
                ++是内部函数;
                const auto ···temp·0·_6 = .获取符号标志(nn);
                .声明符号并添加到符号表((cast(节点_)(nn)), .获取名称(nn), ···temp·0·_6[0], ···temp·0·_6[1]);
                --是内部函数;
                break;
            }
            case KSK.函数类型: {
                .绑定函数类型((cast(函数类型_)(nn)));
                break;
            }
            case KSK.函数表达式: {
                ++是内部函数;
                .绑定函数表达式((cast(函数表达式_)(nn)));
                --是内部函数;
                break;
            }
            case KSK.箭头函数: {
                ++是内部函数;
                .绑定箭头函数((cast(箭头函数_)(nn)));
                --是内部函数;
                break;
            }
            case KSK.结构字面量表达式:
            case KSK.接口字面量表达式: {
                .绑定结构字面量表达式(nn);
                break;
            }
            default: {
                break;
            }
        }
    }
}
符号标志_ 获取扩展符号标志组(节点_ n) {
    节点数组_!(修饰符_) ns = n.修饰符;
    符号标志_ 修饰符 = 符号标志_.无_;
    if ((ns !is null) && (ns.原型 !is ··null!(修饰符_[])) && ns.length > 0) {
        foreach (修饰符_ v; ns) {
            修饰符 |= 获取扩展符号标志(v.目标种类);
        }
    }
    if (n.目标种类 == KSK.变量声明) {
        节点_ pn = (cast(节点_)(n.父节点));
        修饰符 |= .获取扩展符号标志组(pn);
    }
    if (n.目标种类 == KSK.变量声明列表) {
        节点_ pn = (cast(节点_)(n.父节点));
        修饰符 |= .获取扩展符号标志组(pn);
    }
    return 修饰符;
}
void 报告修饰符错误(节点_ n, 修饰符标志_ 修饰符, 诊断消息_ 错误消息, dstring arg0 = ··null!(dstring), dstring arg1 = ··null!(dstring)) {
    if ((n.修饰符 !is null) && (n.修饰符.原型 !is ··null!(修饰符_[])) && n.修饰符.length > 0) {
        修饰符_[] 过滤后的 = 过滤!(修饰符_)(n.修饰符, (修饰符_ e) { return (修饰符种类转标志(e.目标种类) & 修饰符) != 0; });
        if ((过滤后的 !is ··null!(修饰符_[])) && 过滤后的.length > 0) {
            foreach (修饰符_ e; 过滤后的) {
                .error(e, 错误消息, arg0, arg1);
            }
        }
    }
    if (n.目标种类 == KSK.变量声明) {
        节点_ pn = (cast(节点_)(n.父节点));
        .报告修饰符错误(pn, 修饰符, 错误消息, arg0, arg1);
    }
    if (n.目标种类 == KSK.变量声明列表) {
        节点_ pn = (cast(节点_)(n.父节点));
        .报告修饰符错误(pn, 修饰符, 错误消息, arg0, arg1);
    }
}
auto 获取符号标志(节点_ n) {
    long k = n.目标种类;
    符号标志_ 标志 = .获取扩展符号标志组(n);
    if ((标志 & 符号标志_.外部_) != 0) {
        switch (k) {
            case KSK.枚举声明:
            case KSK.函数声明:
            case KSK.结构声明:
            case KSK.变量声明: {
                break;
            }
            default: {
                // err 不支持外部修饰符;
                .报告修饰符错误(n, 修饰符标志_.外部_, 诊断集_.这里不支持_0_修饰符, "外部"d);
                标志 = 符号标志_.无_;
                break;
            }
        }
        bool 有外部 = (.当前的外部修饰符 !is ··null!(外部修饰符声明_));
        foreach (修饰符_ v; n.修饰符) {
            if (v.目标种类 == KSK.外部修饰符声明) {
                if (有外部) {
                    // err 多个 外部修饰符
                    .error(v, 诊断集_.修饰符_0_重复, "外部"d);
                    标志 = 符号标志_.无_;
                    break;
                }
                .当前的外部修饰符 = (cast(外部修饰符声明_)(v));
                有外部 = .当前的外部修饰符 !is ··null!(外部修饰符声明_);
            }
        }
    }
    else {
        switch (k) {
            case KSK.导入从成员: {
                if (标志 != 符号标志_.无_) {
                    .报告修饰符错误(n, 修饰符标志_.全部_, 诊断集_.这里不支持_0_修饰符, "所有的"d);
                    标志 = 符号标志_.无_;
                }
                break;
            }
            case KSK.导入成员: {
                if (标志 != 符号标志_.无_) {
                    if ((标志 & ~符号标志_.公开_) != 0) {
                        // err 只支持 公开_
                        .报告修饰符错误(n, 修饰符标志_.公开_, 诊断集_.这里不支持_0_修饰符, "除'公开'以外的其他"d);
                        标志 = 符号标志_.公开_;
                    }
                }
                break;
            }
            case KSK.形参声明: {
                if (标志 != 符号标志_.无_) {
                    if ((标志 & ~符号标志_.返回局部引用_) != 0) {
                        // err 只支持 返回局部引用_
                        .报告修饰符错误(n, 修饰符标志_.返局引_, 诊断集_.这里不支持_0_修饰符, "除'返回、局部、引用'以外的其他"d);
                        标志 = (标志 & 符号标志_.返回局部引用_);
                    }
                }
                if (((cast(形参声明_)(n)).问号 !is ··null!(KSK)) || ((cast(形参声明_)(n)).初始化 !is ··null!(节点_))) {
                    标志 |= 符号标志_.可选_;
                }
                break;
            }
            case KSK.索引签名:
            case KSK.运算符签名: {
                if (标志 != 符号标志_.无_) {
                    // 不支持 修饰符;
                    // 排除父级修饰符
                    .报告修饰符错误(n, 修饰符标志_.全部_, 诊断集_.这里不支持_0_修饰符, "所有的"d);
                }
                标志 = 符号标志_.无_;
                break;
            }
            case KSK.类型形参: {
                if ((标志 & 符号标志_.返回局部引用_) != 0) {
                    if ((标志 & ~符号标志_.返回局部引用_) != 0) {
                        // err 不支持其他的
                        .报告修饰符错误(n, 修饰符标志_.返局引_, 诊断集_.这里不支持_0_修饰符, "除'返回、局部、引用'以外的其他"d);
                    }
                    break;
                }
            }
            // 贯穿
            case KSK.枚举成员:
            case KSK.简洁属性赋值:
            case KSK.属性赋值: {
                if (标志 != 符号标志_.无_) {
                    // 不支持 修饰符;
                    // 排除父级修饰符
                    .报告修饰符错误(n, 修饰符标志_.全部_, 诊断集_.这里不支持_0_修饰符, "所有的"d);
                }
                标志 = 符号标志_.无_;
                break;
            }
            case KSK.函数声明: {
                if (.是内部函数 > 0) {
                    // 排除父级
                    if (标志 != 符号标志_.无_) {
                        if ((标志 & ~(符号标志_.静态_ | 符号标志_.只读_ | 符号标志_.恒定_ | 符号标志_.共享_)) != 0) {
                            // err 只支持 静态 只读 恒定 共享
                            .报告修饰符错误(n, 修饰符标志_.静态只读恒定共享以外的_, 诊断集_.这里不支持_0_修饰符, "除'静态、只读、恒定、共享'以外的其他"d);
                            标志 = 符号标志_.无_;
                        }
                        else if ((标志 & 符号标志_.只读_) != 0 && (标志 & 符号标志_.恒定_) != 0) {
                            // err 同时具有 只读 和 恒定
                            .报告修饰符错误(n, 修饰符标志_.只读_ | 修饰符标志_.恒定_, 诊断集_.修饰符_0_与_1_不能同存在, "只读"d, "恒定"d);
                            标志 = 符号标志_.无_;
                        }
                    }
                    标志 |= 符号标志_.内部声明_;
                    break;
                }
            }
            // 贯穿;
            case KSK.变量声明:
            case KSK.别名声明:
            case KSK.类型声明:
            case KSK.枚举声明:
            case KSK.构建声明:
            case KSK.释放声明:
            case KSK.属性声明: {
                if ((标志 & 符号标志_.固定_) != 0) {
                    // err 不支持;
                    .报告修饰符错误(n, 修饰符标志_.固定_, 诊断集_.这里不支持_0_修饰符, "固定"d);
                    标志 = 符号标志_.无_;
                }
            }
            // 贯穿;
            case KSK.方法声明:
            case KSK.结构声明:
            case KSK.对象声明: {
                if ((标志 & 符号标志_.重载_) != 0) {
                    // err 不支持
                    if (k != KSK.方法声明 && k != KSK.属性声明) {
                        .报告修饰符错误(n, 修饰符标志_.重载_, 诊断集_.这里不支持_0_修饰符, "重载"d);
                        标志 = 符号标志_.无_;
                    }
                    else if (container.目标种类 == KSK.接口声明) {
                        .报告修饰符错误(n, 修饰符标志_.重载_, 诊断集_.这里不支持_0_修饰符, "重载"d);
                        标志 = 符号标志_.无_;
                    }
                    else if (container.目标种类 == KSK.结构声明 && k == KSK.方法声明) {
                        .报告修饰符错误(n, 修饰符标志_.重载_, 诊断集_.这里不支持_0_修饰符, "重载"d);
                        标志 = 符号标志_.无_;
                    }
                }
                if ((标志 & 符号标志_.返回_) != 0) {
                    // err 不支持
                    .报告修饰符错误(n, 修饰符标志_.返回_, 诊断集_.这里不支持_0_修饰符, "返回"d);
                    标志 = 符号标志_.无_;
                }
                if ((标志 & 符号标志_.局部_) != 0) {
                    // err 不支持
                    .报告修饰符错误(n, 修饰符标志_.局部_, 诊断集_.这里不支持_0_修饰符, "局部"d);
                    标志 = 符号标志_.无_;
                }
                if ((标志 & 符号标志_.引用_) != 0) {
                    // err 不支持
                    .报告修饰符错误(n, 修饰符标志_.引用_, 诊断集_.这里不支持_0_修饰符, "引用"d);
                    标志 = 符号标志_.无_;
                }
                if ((标志 & 符号标志_.只读_) != 0 && (.声明块符号标志组 & 符号标志_.恒定_) != 0) {
                    if ((.声明块符号标志组 & 符号标志_.恒定_) != 0) {
                        // 冲突
                        .报告修饰符错误(n, 修饰符标志_.只读_ | 修饰符标志_.恒定_, 诊断集_.修饰符_0_与_1_不能同存在, "只读"d, "恒定"d);
                        标志 = 符号标志_.无_;
                    }
                }
                if ((标志 & 符号标志_.私有_) != 0 && container.目标种类 == KSK.接口声明) {
                    .报告修饰符错误(n, 修饰符标志_.重载_, 诊断集_.这里不支持_0_修饰符, "私有"d);
                    标志 = 符号标志_.无_;
                }
                if ((标志 & 符号标志_.私有_) != 0 && (.声明块符号标志组 & 符号标志_.保护_) != 0 || (标志 & 符号标志_.保护_) != 0 && (.声明块符号标志组 & 符号标志_.私有_) != 0) {
                    // 私有 和 保护 冲突
                    .报告修饰符错误(n, 修饰符标志_.私有_ | 修饰符标志_.保护_, 诊断集_.修饰符_0_与_1_不能同存在, "私有"d, "保护"d);
                    标志 = 符号标志_.无_;
                }
                else if ((标志 & 符号标志_.导出_) != 0 && (.声明块符号标志组 & 符号标志_.保护_) != 0 || (标志 & 符号标志_.保护_) != 0 && (.声明块符号标志组 & 符号标志_.导出_) != 0) {
                    // 导出 和 保护 冲突
                    .报告修饰符错误(n, 修饰符标志_.导出_ | 修饰符标志_.保护_, 诊断集_.修饰符_0_与_1_不能同存在, "导出"d, "保护"d);
                    标志 = 符号标志_.无_;
                }
                else if ((标志 & 符号标志_.导出_) != 0 && (.声明块符号标志组 & 符号标志_.私有_) != 0 || (标志 & 符号标志_.私有_) != 0 && (.声明块符号标志组 & 符号标志_.导出_) != 0) {
                    // 导出 和 私有 冲突
                    .报告修饰符错误(n, 修饰符标志_.导出_ | 修饰符标志_.私有_, 诊断集_.修饰符_0_与_1_不能同存在, "导出"d, "私有"d);
                    标志 = 符号标志_.无_;
                }
                if (k == KSK.别名声明 || k == KSK.类型声明 || k == KSK.枚举声明 || k == KSK.结构声明 || k == KSK.对象声明) {
                    .父级标志 = 标志;
                }
                if (k == KSK.方法声明 || k == KSK.构建声明 || k == KSK.属性声明 || k == KSK.释放声明) {
                    if (n.父节点.目标种类 == KSK.块 && ((cast(块_)(n.父节点)).版本容器块种类 & 版本容器块种类_.是局部声明块_) == 0) {
                        标志 |= (.声明块符号标志组 & ~(符号标志_.私有_ | 符号标志_.保护_));
                    }
                    else {
                        if ((标志 & 符号标志_.私有_) != 0 && (标志 & 符号标志_.保护_) != 0) {
                            标志 |= .声明块符号标志组;
                        }
                        else if ((标志 & 符号标志_.私有_) != 0) {
                            标志 |= (.声明块符号标志组 & ~符号标志_.保护_);
                        }
                        else if ((标志 & 符号标志_.保护_) != 0) {
                            标志 |= (.声明块符号标志组 & ~符号标志_.私有_);
                        }
                        if ((.父级标志 & (符号标志_.只读_ | 符号标志_.恒定_ | 符号标志_.共享_ | 符号标志_.静态_)) != 0) {
                            if ((.父级标志 & 符号标志_.静态_) != 0) {
                                标志 |= 符号标志_.静态_;
                            }
                            if ((.父级标志 & 符号标志_.恒定_) != 0) {
                                标志 &= ~符号标志_.只读_;
                                标志 |= 符号标志_.恒定_;
                            }
                            if ((.父级标志 & 符号标志_.只读_) != 0) {
                                if ((标志 & 符号标志_.恒定_) == 0) {
                                    标志 |= 符号标志_.只读_;
                                }
                            }
                            if ((.父级标志 & 符号标志_.共享_) != 0) {
                                标志 |= 符号标志_.共享_;
                            }
                        }
                    }
                }
                else {
                    标志 |= .声明块符号标志组;
                }
                break;
            }
            default: break;
        }
    }
    switch (k) {
        case KSK.变量声明: {
            if (是局部变量声明((cast(变量声明_)(n)))) {
                return ·tuple(符号标志_.局部变量_ | (标志 & ~.声明块符号标志组), 符号标志_.局部变量排除_);
            }
            else {
                return ·tuple(符号标志_.全局变量_ | 标志, 符号标志_.全局变量排除_);
            }
        }
        case KSK.形参声明: {
            return ·tuple(符号标志_.形参声明_ | 标志, 符号标志_.形参声明排除_);
        }
        case KSK.构建声明: {
            return ·tuple(符号标志_.构建_ | 标志, ((.声明块符号标志组 & 符号标志_.静态_) != 0 ? 符号标志_.全部_ : 符号标志_.构建排除_));
        }
        case KSK.释放声明: {
            return ·tuple(符号标志_.释放_ | 标志, 符号标志_.释放排除_);
        }
        case KSK.方法声明: {
            return ·tuple(符号标志_.方法_ | 标志, 符号标志_.方法排除_);
        }
        case KSK.索引签名: {
            return ·tuple(符号标志_.索引签名_ | 标志, 符号标志_.索引签名排除_);
        }
        case KSK.运算符签名: {
            return ·tuple(符号标志_.运算符签名_ | 标志, 符号标志_.运算符签名排除_);
        }
        case KSK.属性赋值:
        case KSK.简洁属性赋值:
        case KSK.属性声明: {
            return ·tuple(符号标志_.属性_ | 标志, 符号标志_.属性排除_);
        }
        case KSK.导入从成员: {
            return ·tuple(符号标志_.别名_ | 标志, 符号标志_.别名排除_);
        }
        case KSK.导入成员: {
            return ·tuple(符号标志_.别名_ | 符号标志_.程序集导入_ | 标志, 符号标志_.别名排除_);
        }
        case KSK.类型形参: {
            return ·tuple(符号标志_.类型形参_, 符号标志_.类型形参排除_);
        }
        case KSK.枚举成员: {
            return ·tuple(符号标志_.枚举成员_ | 标志, 符号标志_.枚举成员排除_);
        }
        case KSK.函数声明: {
            return ·tuple(符号标志_.函数_ | 标志, 符号标志_.函数排除_);
        }
        case KSK.结构声明: {
            return ·tuple(符号标志_.结构_ | 标志, 符号标志_.结构排除_);
        }
        case KSK.对象声明: {
            return ·tuple(符号标志_.对象_ | 标志, 符号标志_.对象排除_);
        }
        case KSK.接口声明: {
            return ·tuple(符号标志_.接口_ | 标志, 符号标志_.接口排除_);
        }
        case KSK.别名声明: {
            return ·tuple(符号标志_.类型别名_ | 标志, 符号标志_.类型别名排除_);
        }
        case KSK.类型声明: {
            return ·tuple(符号标志_.类型声明_ | 标志, 符号标志_.类型声明排除_);
        }
        case KSK.枚举声明: {
            return ·tuple(符号标志_.枚举声明_ | 标志, 符号标志_.枚举声明排除_);
        }
        default: break;
    }
    return ·tuple(标志, 符号标志_.无_);
}
dstring 获取名称(基础节点.节点_ node) {
    if (是klang节点(node)) {
        节点_ n = (cast(节点_)(node));
        long ksk = n.目标种类;
        switch (ksk) {
            case KSK.运算符签名: {
                return 内部符号名_.运算符_;
            }
            case KSK.索引签名: {
                return 内部符号名_.索引_;
            }
            case KSK.构建声明: {
                return 内部符号名_.新建_;
            }
            case KSK.释放声明: {
                return 内部符号名_.释放_;
            }
            case KSK.导入从成员: {
                导入从成员_ nn = (cast(导入从成员_)(n));
                if (nn.另命名名称 !is ··null!(标识符_)) {
                    return nn.另命名名称.标识符.内容;
                }
                return nn.名称.标识符.内容;
            }
            case KSK.导入成员: {
                导入成员_ nn = (cast(导入成员_)(n));
                if (nn.另命名名称 !is ··null!(标识符_)) {
                    dstring 名称 = nn.另命名名称.标识符.内容;
                    nn.符号名 = 名称;
                    return 名称;
                }
                dstring 名称 = 获取基础文件名称(nn.模块名.内容);
                nn.符号名 = 名称;
                return 名称;
            }
            case KSK.变量声明: {
                变量声明_ nn = (cast(变量声明_)(n));
                dstring 名称 = nn.名称.标识符.内容;
                return 名称;
            }
            case KSK.程序声明: {
                程序声明_ nn = (cast(程序声明_)(n));
                if (nn.名称 is ··null!(标识符_)) {
                    路径和路径片段_ 路径片段 = 正规化路径和片段(获取目录路径(file.文件名));
                    dstring 目录名 = 路径片段.片段[路径片段.片段.length - 1];
                    return 目录名 == "源码"d ? "启动"d : 目录名;
                }
                dstring 名称 = nn.名称.标识符.内容;
                return 名称;
            }
            case KSK.对象声明: {
                对象声明_ nn = (cast(对象声明_)(n));
                dstring 名称 = nn.名称.标识符.内容;
                return 名称;
            }
            case KSK.结构声明: {
                结构声明_ nn = (cast(结构声明_)(n));
                dstring 名称 = nn.名称.标识符.内容;
                return 名称;
            }
            case KSK.接口声明: {
                接口声明_ nn = (cast(接口声明_)(n));
                dstring 名称 = nn.名称.标识符.内容;
                return 名称;
            }
            case KSK.别名声明: {
                别名声明_ nn = (cast(别名声明_)(n));
                dstring 名称 = nn.名称.标识符.内容;
                return 名称;
            }
            case KSK.类型声明: {
                类型声明_ nn = (cast(类型声明_)(n));
                dstring 名称 = nn.名称.标识符.内容;
                return 名称;
            }
            case KSK.函数声明: {
                函数声明_ nn = (cast(函数声明_)(n));
                dstring 名称 = nn.名称.标识符.内容;
                return 名称;
            }
            case KSK.方法声明: {
                方法声明_ nn = (cast(方法声明_)(n));
                dstring 名称 = nn.名称.标识符.内容;
                return 名称;
            }
            case KSK.形参声明: {
                形参声明_ nn = (cast(形参声明_)(n));
                dstring 名称 = nn.名称.标识符.内容;
                return 名称;
            }
            case KSK.类型形参: {
                类型形参_ nn = (cast(类型形参_)(n));
                dstring 名称 = nn.名称.标识符.内容;
                return 名称;
            }
            case KSK.属性声明: {
                属性声明_ nn = (cast(属性声明_)(n));
                dstring 名称 = nn.名称.标识符.内容;
                return 名称;
            }
            case KSK.属性赋值: {
                属性赋值_ nn = (cast(属性赋值_)(n));
                dstring 名称 = nn.名称.标识符.内容;
                return 名称;
            }
            case KSK.简洁属性赋值: {
                简洁属性赋值_ nn = (cast(简洁属性赋值_)(n));
                dstring 名称 = nn.名称.标识符.内容;
                return 名称;
            }
            case KSK.枚举声明: {
                枚举声明_ nn = (cast(枚举声明_)(n));
                dstring 名称 = nn.名称.标识符.内容;
                return 名称;
            }
            case KSK.枚举成员: {
                枚举成员_ nn = (cast(枚举成员_)(n));
                dstring 名称 = nn.名称.标识符.内容;
                return 名称;
            }
            default: break;
        }
    }
    return ""d;
}
void 绑定程序声明(程序声明_ node) {
    符号_ 程序符号 = .声明符号(file.本地组, node, .获取名称(node), ··null!(符号_), 符号标志_.程序集_, 符号标志_.程序集排除_);
    程序符号.碎裂名称 = .追加!(dstring)(.包名, 程序符号.名称);
}
void 绑定函数类型(函数类型_ n) {
    符号_ 符号 = .创建符号(符号标志_.签名_, 内部符号名_.调用_);
    .添加符号声明(符号, n, 符号标志_.签名_);
    符号_ 类型符号 = .创建符号(符号标志_.类型字面量_, 内部符号名_.类型_);
    .添加符号声明(类型符号, n, 符号标志_.类型字面量_);
    类型符号.成员 = 创建符号表();
    类型符号.成员.p·设置(内部符号名_.调用_, 符号);
}
void 绑定函数表达式(函数表达式_ n) {
    if (.currentFlow !is ··null!(流节点_)) {
        n.流节点 = .currentFlow;
    }
    dstring 名称 = n.名称 ? n.名称.标识符.内容 : 内部符号名_.函数_;
    .绑定匿名声明(n, 符号标志_.函数_ | 符号标志_.内部声明_, 名称);
}
void 绑定箭头函数(箭头函数_ n) {
    if (.currentFlow !is ··null!(流节点_)) {
        n.流节点 = .currentFlow;
    }
    .绑定匿名声明(n, 符号标志_.函数_ | 符号标志_.内部声明_, 内部符号名_.函数_);
}
void 绑定结构字面量表达式(节点_ n) {
    .绑定匿名声明(n, 符号标志_.结构字面量_, 内部符号名_.对象_);
}
符号_ 绑定匿名声明(节点_ n, 符号标志_ 符号标志, dstring 名称) {
    符号_ 符号 = .创建符号(符号标志, 名称);
    if ((符号标志 & 符号标志_.枚举成员_) != 0) {
        符号.父符号 = container.符号;
    }
    .添加符号声明(符号, n, 符号标志);
    return 符号;
}
void 绑定子工作站(基础节点.节点_ node) {
    容器标志_ 是容器 = .获取容器标志(node);
    if (是容器 != 容器标志_.无_) {
        .绑定容器节点(node, 是容器);
    }
    else {
        .绑定子节点(node);
    }
}
bool 绑定包装(基础节点.节点_ node) {
    .绑定函数(node);
    return false;
}
bool 绑定节点组包装(节点数组_!(基础节点.节点_) nodes) {
    循环每个!(基础节点.节点_, void*)(nodes, (基础节点.节点_ v, size_t i) {
        ((基础节点.节点_ nn, size_t _) { return .绑定函数(nn); })(v, i);
        return null;
    });
    return false;
}
bool 绑定每个成员(节点数组_!(基础节点.节点_) nodes = ··null!(节点数组_!(基础节点.节点_))) {
    if ((nodes is null) || (nodes.原型 is ··null!(基础节点.节点_[]))) {
        return false;
    }
    return .绑定节点组包装(nodes);
}
bool 绑定包装函数优先(基础节点.节点_ node) {
    if (node.目标种类 == KSK.函数声明 || node.目标种类 == KSK.版本语句 || node.目标种类 == KSK.版本表达式语句) {
        .绑定函数(node);
    }
    return false;
}
bool 绑定节点组包装函数优先(节点数组_!(基础节点.节点_) nodes) {
    循环每个!(基础节点.节点_, bool)(nodes, (基础节点.节点_ nn, size_t _) { return .绑定包装函数优先(nn); });
    return false;
}
bool 绑定包装非函数优先(基础节点.节点_ node) {
    if (node.目标种类 != KSK.函数声明 && node.目标种类 != KSK.版本语句 && node.目标种类 != KSK.版本表达式语句) {
        .绑定函数(node);
    }
    return false;
}
bool 绑定节点组包装非函数优先(节点数组_!(基础节点.节点_) nodes) {
    循环每个!(基础节点.节点_, bool)(nodes, (基础节点.节点_ nn, size_t _) { return .绑定包装非函数优先(nn); });
    return false;
}
void 绑定每个子节点(基础节点.节点_ node) {
    遍历节点(node, cast(bool delegate(基础节点.节点_))(·fd(&.绑定包装)), cast(bool delegate(节点数组_!(基础节点.节点_)))(·fd(&.绑定节点组包装)));
}
void 优先绑定函数声明(基础节点.节点_ node) {
    遍历节点(node, cast(bool delegate(基础节点.节点_))(·fd(&.绑定包装函数优先)), cast(bool delegate(节点数组_!(基础节点.节点_)))(·fd(&.绑定节点组包装函数优先)));
    遍历节点(node, cast(bool delegate(基础节点.节点_))(·fd(&.绑定包装非函数优先)), cast(bool delegate(节点数组_!(基础节点.节点_)))(·fd(&.绑定节点组包装非函数优先)));
}
bool 是可收窄表达式(节点_ expr) {
    switch (expr.目标种类) {
        case KSK.标识符:
        case KSK.本体_:
        case KSK.原型_:
        case KSK.属性访问表达式:
        case KSK.元素访问表达式: {
            return .是可收窄引用(expr);
        }
        case KSK.符号引用表达式: {
            符号引用表达式_ e = (cast(符号引用表达式_)(expr));
            return .是可收窄表达式(e.表达式);
        }
        case KSK.类型转换表达式: {
            类型转换表达式_ e = (cast(类型转换表达式_)(expr));
            return .是可收窄表达式(e.表达式);
        }
        case KSK.类型断言表达式: {
            类型断言表达式_ e = (cast(类型断言表达式_)(expr));
            return .是可收窄表达式(e.表达式);
        }
        case KSK.类型查询表达式: {
            类型查询表达式_ e = (cast(类型查询表达式_)(expr));
            return .是可收窄表达式(e.表达式);
        }
        case KSK.调用表达式: {
            调用表达式_ e = (cast(调用表达式_)(expr));
            return .有可收窄实参(e);
        }
        case KSK.二元表达式: {
            二元表达式_ e = (cast(二元表达式_)(expr));
            return .是可收窄二元表达式(e);
        }
        case KSK.前缀一元表达式: {
            前缀一元表达式_ e = (cast(前缀一元表达式_)(expr));
            return e.运算符 == KSK.叹号 && .是可收窄表达式(e.表达式);
        }
        default: break;
    }
    return false;
}
bool 是可收窄引用(节点_ expr) {
    if (expr.目标种类 == KSK.标识符 || expr.目标种类 == KSK.基类_ || expr.目标种类 == KSK.本体_ || expr.目标种类 == KSK.原型_) {
        return true;
    }
    if (expr.目标种类 == KSK.符号引用表达式) {
        符号引用表达式_ e = (cast(符号引用表达式_)(expr));
        return .是可收窄引用(e.表达式);
    }
    if (是属性访问表达式(expr)) {
        属性访问表达式_ e = (cast(属性访问表达式_)(expr));
        return .是可收窄引用(e.左侧);
    }
    if (是非空表达式(expr)) {
        非空表达式_ e = (cast(非空表达式_)(expr));
        return .是可收窄引用(e.表达式);
    }
    if (是元素访问表达式(expr)) {
        元素访问表达式_ e = (cast(元素访问表达式_)(expr));
        if (是klang文本字面量(e.参数表达式) || 是klang数字字面量(e.参数表达式)) {
            return .是可收窄引用(e.表达式);
        }
    }
    return false;
}
bool 有可收窄实参(调用表达式_ expr) {
    if ((expr.实参组 !is null) && (expr.实参组.原型 !is ··null!(节点_[]))) {
        foreach (节点_ argument; expr.实参组) {
            if (.是可收窄引用(argument)) {
                return true;
            }
        }
    }
    if (expr.表达式.目标种类 == KSK.属性访问表达式) {
        属性访问表达式_ e = (cast(属性访问表达式_)(expr.表达式));
        if (.是可收窄引用(e.左侧)) {
            return true;
        }
    }
    return false;
}
bool 是可收窄二元表达式(二元表达式_ expr) {
    switch (expr.运算符) {
        case KSK.等号: {
            return .是可收窄引用(expr.左侧);
        }
        case KSK.等等号:
        case KSK.叹等号: {
            return .是可收窄算子(expr.左侧) || .是可收窄算子(expr.右侧);
        }
        default: break;
    }
    return false;
}
bool 是可收窄算子(节点_ expr) {
    switch (expr.目标种类) {
        case KSK.二元表达式: {
            二元表达式_ e = (cast(二元表达式_)(expr));
            switch (e.运算符) {
                case KSK.等号: {
                    return .是可收窄算子(e.左侧);
                }
                default: break;
            }
        }
        default: break;
    }
    return .是可收窄引用(expr);
}
void 绑定容器节点(基础节点.节点_ node, 容器标志_ 标志) {
    基础节点.节点_ saveContainer = .container;
    基础节点.节点_ 储存的外部容器 = .外部容器节点;
    基础节点.节点_ 储存当前程序集节点 = .当前程序集节点;
    基础节点.节点_ 储存当前范围容器节点 = .当前范围容器节点;
    基础节点.节点_ savedBlockScopeContainer = .blockScopeContainer;
    if ((标志 & 容器标志_.是外部容器_) != 0) {
        .外部容器节点 = node;
    }
    if ((标志 & 容器标志_.是程序集容器_) != 0) {
        .当前程序集节点 = node;
    }
    if ((标志 & 容器标志_.是范围容器_) != 0) {
        .当前范围容器节点 = node;
    }
    if ((标志 & 容器标志_.是容器_) != 0) {
        .blockScopeContainer = node;
        .container = .blockScopeContainer;
        if ((标志 & 容器标志_.有本地组_) != 0) {
            node.本地组 = 创建符号表();
        }
        .addToContainerChain(.container);
    }
    else if ((标志 & 容器标志_.是块范围容器_) != 0) {
        .blockScopeContainer = node;
    }
    if ((标志 & 容器标志_.是控制流容器_) != 0) {
        流节点_ delegate(流节点_) saveFlowNodeCreated = cast(流节点_ delegate(流节点_))(.flowNodeCreated);
        流节点_ saveCurrentFlow = .currentFlow;
        流节点_ saveBreakTarget = .currentBreakTarget;
        流节点_ saveContinueTarget = .currentContinueTarget;
        流节点_ saveReturnTarget = .currentReturnTarget;
        活动标签_[] saveActiveLabels = .activeLabels;
        bool saveHasExplicitReturn = .hasExplicitReturn;
        流节点_ saveCurrentExceptionTarget = .currentExceptionTarget;
        bool 是立即调用 = false;
        if ((标志 & 容器标志_.是函数表达式_) != 0) {
            调用表达式_ cn = 获取立即调用函数表达式(node);
            if (cn !is ··null!(调用表达式_)) {
                是立即调用 = true;
            }
        }
        if (!是立即调用) {
            .currentFlow = .initFlowNode(new 流节点_(流标志_.Start));
            if ((标志 & 容器标志_.是函数表达式_) != 0) {
                currentFlow.node = node;
            }
        }
        if (是立即调用 || 是klang节点(node) && (cast(节点_)(node)).目标种类 == KSK.构建声明) {
            .currentReturnTarget = .createBranchLabel();
        }
        else {
            .currentReturnTarget = ··null!(流节点_);
        }
        .currentExceptionTarget = ··null!(流节点_);
        .currentBreakTarget = ··null!(流节点_);
        .currentContinueTarget = ··null!(流节点_);
        .activeLabels = ··null!(活动标签_[]);
        .hasExplicitReturn = false;
        .flowNodeCreated = cast(流节点_ delegate(流节点_))(·fd(&.initFlowNode));
        .绑定子节点(node);
        node.标志 &= (cast(整数_)(~节点标志_.ReachabilityAndEmitFlags));
        if ((currentFlow.标志 & 流标志_.Unreachable) == 0 && (标志 & 容器标志_.是函数类的_) != 0) {
            节点_ fn = (cast(节点_)(node));
            if (是函数类声明(fn)) {
                函数类声明_ fnd = (cast(函数类声明_)(fn));
                if (fnd.函数体 !is ··null!(基础节点.节点_)) {
                    fnd.标志 |= (cast(整数_)(节点标志_.HasImplicitReturn));
                    if (.hasExplicitReturn) {
                        fnd.标志 |= (cast(整数_)(节点标志_.HasExplicitReturn));
                    }
                    fnd.结尾流 = .currentFlow;
                }
            }
        }
        if (.currentReturnTarget !is ··null!(流节点_)) {
            .addAntecedent(.currentReturnTarget, .currentFlow);
            .currentFlow = .finishFlowLabel(.currentReturnTarget);
            if (node.目标种类 == KSK.构建声明) {
                构建声明_ cn = (cast(构建声明_)(node));
                cn.返回流节点 = .currentFlow;
            }
        }
        if (!是立即调用) {
            .currentFlow = saveCurrentFlow;
        }
        .currentBreakTarget = saveBreakTarget;
        .currentContinueTarget = saveContinueTarget;
        .currentReturnTarget = saveReturnTarget;
        .currentExceptionTarget = saveCurrentExceptionTarget;
        .activeLabels = saveActiveLabels;
        .hasExplicitReturn = saveHasExplicitReturn;
        .flowNodeCreated = cast(流节点_ delegate(流节点_))(saveFlowNodeCreated);
    }
    else {
        .绑定子节点(node);
    }
    .container = saveContainer;
    .外部容器节点 = 储存的外部容器;
    .当前程序集节点 = 储存当前程序集节点;
    .当前范围容器节点 = 储存当前范围容器节点;
    .blockScopeContainer = savedBlockScopeContainer;
}
void addToContainerChain(基础节点.节点_ next) {
    if (.lastContainer !is ··null!(基础节点.节点_)) {
        lastContainer.下个容器 = next;
    }
    .lastContainer = next;
}
void setFlowNodeReferenced(流节点_ flow) {
    // On first reference we set the Referenced flag, thereafter we set the Shared flag
    flow.标志 |= ((flow.标志 & 流标志_.Referenced) != 0 ? 流标志_.Shared : 流标志_.Referenced);
}
流节点_ createFlowSwitchClause(流节点_ antecedent, 假如语句_ switchStatement, long clauseStart, long clauseEnd) {
    if (!.是可收窄表达式(switchStatement.表达式)) {
        return antecedent;
    }
    .setFlowNodeReferenced(antecedent);
    流节点_ 流 = new 流节点_(流标志_.SwitchClause);
    流.antecedent = antecedent;
    流.switchStatement = switchStatement;
    流.clauseStart = clauseStart;
    流.clauseEnd = clauseEnd;
    return .flowNodeCreated(流);
}
流节点_ createFlowMutation(流标志_ flags, 流节点_ antecedent, 节点_ node) {
    .setFlowNodeReferenced(antecedent);
    流节点_ result = .initFlowNode(new 流节点_(flags));
    result.antecedent = antecedent;
    result.node = node;
    if (.currentExceptionTarget !is ··null!(流节点_)) {
        .addAntecedent(.currentExceptionTarget, result);
    }
    return result;
}
流节点_ createFlowCall(流节点_ antecedent, 调用表达式_ node) {
    .setFlowNodeReferenced(antecedent);
    流节点_ 流 = new 流节点_(流标志_.Call);
    流.antecedent = antecedent;
    流.node = node;
    return .flowNodeCreated(流);
}
流节点_ createFlowArrayMutation(流节点_ antecedent, 节点_ node) {
    .setFlowNodeReferenced(antecedent);
    流节点_ 流 = new 流节点_(流标志_.ArrayMutation);
    流.antecedent = antecedent;
    流.node = node;
    return .flowNodeCreated(流);
}
/** 添加前兆 */
void addAntecedent(流节点_ label, 流节点_ antecedent) {
    if ((antecedent.标志 & 流标志_.Unreachable) == 0 && ((label.antecedents is ··null!(流节点_[])) || !包含!(流节点_)(label.antecedents, antecedent, (流节点_ a, 流节点_ b) { return a == b; }))) {
        if (label.antecedents is ··null!(流节点_[])) {
            label.antecedents = 创建数组!(流节点_)();
        }
        .追加!(流节点_)(label.antecedents, antecedent);
        .setFlowNodeReferenced(antecedent);
    }
}
流节点_ finishFlowLabel(流节点_ flow) {
    流节点_[] antecedents = flow.antecedents;
    if (antecedents is ··null!(流节点_[])) {
        return .unreachableFlow;
    }
    if (antecedents.length == 1) {
        return antecedents[0];
    }
    return flow;
}
void 绑定子节点(基础节点.节点_ node) {
    if (.checkUnreachable(node)) {
        .绑定每个子节点(node);
        return;
    }
    long k = node.目标种类;
    if (k >= KSK.第一个语句 && k <= KSK.最后一个语句) {
        node.流节点 = .currentFlow;
    }
    switch (k) {
        case KSK.当循环语句: {
            当循环语句_ n = (cast(当循环语句_)(node));
            .绑定当循环语句(n);
            break;
        }
        case KSK.循环语句: {
            循环语句_ n = (cast(循环语句_)(node));
            .bindForStatement(n);
            break;
        }
        case KSK.循环属于: {
            循环属于_ n = (cast(循环属于_)(node));
            .bindForInOrForOfStatement(n);
            break;
        }
        case KSK.如果语句: {
            如果语句_ n = (cast(如果语句_)(node));
            .绑定如果语句(n);
            break;
        }
        case KSK.返回语句: {
            返回语句_ n = (cast(返回语句_)(node));
            .绑定返回语句(n);
            break;
        }
        case KSK.抛出语句: {
            抛出语句_ n = (cast(抛出语句_)(node));
            .绑定抛出语句(n);
            break;
        }
        case KSK.跳出语句: {
            跳出语句_ n = (cast(跳出语句_)(node));
            .绑定跳出语句(n);
            break;
        }
        case KSK.继续语句: {
            继续语句_ n = (cast(继续语句_)(node));
            .绑定继续语句(n);
            break;
        }
        case KSK.尝试语句: {
            尝试语句_ n = (cast(尝试语句_)(node));
            .绑定尝试语句(n);
            break;
        }
        case KSK.假如语句: {
            假如语句_ n = (cast(假如语句_)(node));
            .绑定假如语句(n);
            break;
        }
        case KSK.若是块: {
            若是块_ n = (cast(若是块_)(node));
            .绑定若是块(n);
            break;
        }
        case KSK.若是子句: {
            若是子句_ n = (cast(若是子句_)(node));
            .绑定若是子句(n);
            break;
        }
        case KSK.标签语句: {
            标签语句_ n = (cast(标签语句_)(node));
            .绑定标签语句(n);
            break;
        }
        case KSK.断言语句: {
            .绑定断言语句((cast(断言语句_)(node)));
            break;
        }
        case KSK.前缀一元表达式: {
            .绑定前缀一元表达式((cast(前缀一元表达式_)(node)));
            break;
        }
        case KSK.后缀一元表达式: {
            .绑定后缀一元表达式((cast(后缀一元表达式_)(node)));
            break;
        }
        case KSK.二元表达式: {
            .绑定二元表达式((cast(二元表达式_)(node)));
            break;
        }
        case KSK.条件表达式: {
            .绑定条件表达式((cast(条件表达式_)(node)));
            break;
        }
        case KSK.调用表达式: {
            .绑定调用表达式((cast(调用表达式_)(node)));
            break;
        }
        case KSK.变量声明: {
            .绑定变量声明流((cast(变量声明_)(node)));
            break;
        }
        case KSK.表达式语句: {
            .bindExpressionStatement((cast(表达式语句_)(node)));
            break;
        }
        case KSK.源文件: {
            dstring[] 储存的包名 = .包名;
            Klang源文件_ f = 获取源文件(node);
            if (f.是默认支持库) {
                .包名 = 创建数组!(dstring)();
            }
            else {
                if ((f !is ··null!(Klang源文件_)) && (f.源文件的包 !is ··null!(··klang类型_.klang解析的模块名称_))) {
                    .包名 = (f.源文件的包.包名 !is ··null!(dstring)) && f.源文件的包.包名 != ""d ? [f.源文件的包.包名] : 创建数组!(dstring)();
                    dstring 模块名 = f.源文件的包.模块名称;
                    if (((模块名) !is ··null!(dstring)) && 模块名 != ""d) {
                        路径和路径片段_ 路径和组件 = 正规化路径和片段(模块名);
                        dstring[] 路径片段 = 路径和组件.片段[0 .. $];
                        .追加!(dstring)(.包名, 路径片段);
                    }
                }
                else {
                    dstring 文件名 = ·to!(dstring)(f.文件名);
                    dstring 当前目录 = 正规化路径和片段(当前主机.获取当前目录() ~ "/测试/源码"d).路径;
                    assert(开始包含(文本转小写(文件名), 文本转小写(当前目录)), "不是当前目录内文件."c);
                    dstring 模块名 = 文件名[当前目录.length .. $];
                    dstring[] 模块名组 = 正规化路径和片段(模块名).片段[0 .. $-1];
                    if ((模块名组 !is ··null!(dstring[])) && 模块名组.length > 0) {
                        .追加!(dstring)(.包名, 模块名组);
                    }
                }
            }
            .绑定每个子节点(node);
            f.符号数量 = .符号数量;
            f.文件设置的版本标识符 = .转为文本词典(.文件设置的版本标识符);
            .包名 = 储存的包名;
            break;
        }
        case KSK.程序声明: {
            .优先绑定函数声明(node);
            break;
        }
        case KSK.版本表达式语句: {
            .绑定版本表达式语句((cast(版本表达式语句_)(node)));
            break;
        }
        case KSK.版本语句: {
            .绑定版本语句((cast(版本语句_)(node)));
            break;
        }
        case KSK.导入版本成员: {
            .绑定导入版本成员((cast(导入版本成员_)(node)));
            break;
        }
        case KSK.导入从版本成员: {
            .绑定导入从版本成员((cast(导入从版本成员_)(node)));
            break;
        }
        case KSK.测试单元语句: {
            .绑定测试单元语句((cast(测试单元语句_)(node)));
            break;
        }
        case KSK.导入成员块: {
            核心.去重数组_!(dstring) 储存 = .当前版本路径;
            .当前版本路径 = .转为单维去重数组((cast(导入成员块_)(node)).版本语句路径);
            .绑定每个子节点(node);
            .当前版本路径 = 储存;
            break;
        }
        case KSK.导入从成员块: {
            核心.去重数组_!(dstring) 储存 = .当前版本路径;
            .当前版本路径 = .转为单维去重数组((cast(导入从成员块_)(node)).版本语句路径);
            .绑定每个子节点(node);
            .当前版本路径 = 储存;
            break;
        }
        case KSK.块: {
            符号标志_ 储存声明块符号标志组 = .声明块符号标志组;
            外部修饰符声明_ 储存当前的外部修饰符 = .当前的外部修饰符;
            块_ n = (cast(块_)(node));
            if ((n.版本容器块种类 & (版本容器块种类_.是声明块_ | 版本容器块种类_.是局部声明块_)) != 0) {
                bool 有外部 = (.当前的外部修饰符 !is ··null!(外部修饰符声明_));
                foreach (修饰符_ v; n.修饰符) {
                    符号标志_ 标志 = 获取扩展符号标志(v.目标种类);
                    修饰符标志_ 修饰符标志 = 修饰符种类转标志(v.目标种类);
                    if ((修饰符标志 & 修饰符标志_.外部_) != 0) {
                        if ((n.版本容器块种类 & 版本容器块种类_.是局部声明块_) != 0) {
                            // err 不支持
                            .error(v, 诊断集_.这里不支持_0_修饰符, "外部"d);
                            标志 = 符号标志_.无_;
                        }
                        else if (有外部) {
                            // err 多个 外部
                            .error(v, 诊断集_.修饰符_0_重复, "外部"d);
                            标志 = 符号标志_.无_;
                        }
                        .当前的外部修饰符 = (cast(外部修饰符声明_)(v));
                        有外部 = .当前的外部修饰符 !is ··null!(外部修饰符声明_);
                    }
                    if ((修饰符标志 & 修饰符标志_.返局引_) != 0) {
                        // err 不支持
                        .error(v, 诊断集_.这里不支持_0_修饰符, "返回、局部 或 引用"d);
                        标志 = 符号标志_.无_;
                    }
                    else if ((修饰符标志 & 修饰符标志_.重载_) != 0 && (n.版本容器块种类 & 版本容器块种类_.是局部声明块_) == 0) {
                        // err 不支持
                        .error(v, 诊断集_.这里不支持_0_修饰符, "重载"d);
                        标志 = 符号标志_.无_;
                    }
                    else if ((n.版本容器块种类 & 版本容器块种类_.是局部声明块_) != 0) {
                        if ((修饰符标志 & 修饰符标志_.导出_) != 0) {
                            // 不支持 导出
                            .error(v, 诊断集_.这里不支持_0_修饰符, "导出"d);
                            标志 = 符号标志_.无_;
                        }
                    }
                    else {
                        if ((修饰符标志 & 修饰符标志_.私有_) != 0 && (.声明块符号标志组 & 符号标志_.保护_) != 0 || (修饰符标志 & 修饰符标志_.保护_) != 0 && (.声明块符号标志组 & 符号标志_.私有_) != 0) {
                            // 私有 和 保护 冲突
                            .error(v, 诊断集_.修饰符_0_与_1_不能同存在, "私有"d, "保护"d);
                            标志 = 符号标志_.无_;
                        }
                        else if ((修饰符标志 & 修饰符标志_.导出_) != 0 && (.声明块符号标志组 & 符号标志_.保护_) != 0 || (修饰符标志 & 修饰符标志_.保护_) != 0 && (.声明块符号标志组 & 符号标志_.导出_) != 0) {
                            // 导出 和 保护 冲突
                            .error(v, 诊断集_.修饰符_0_与_1_不能同存在, "导出"d, "保护"d);
                            标志 = 符号标志_.无_;
                        }
                        else if ((修饰符标志 & 修饰符标志_.导出_) != 0 && (.声明块符号标志组 & 符号标志_.私有_) != 0 || (修饰符标志 & 修饰符标志_.私有_) != 0 && (.声明块符号标志组 & 符号标志_.导出_) != 0) {
                            // 导出 和 私有 冲突
                            .error(v, 诊断集_.修饰符_0_与_1_不能同存在, "导出"d, "私有"d);
                            标志 = 符号标志_.无_;
                        }
                    }
                    .声明块符号标志组 |= 标志;
                }
            }
            核心.去重数组_!(dstring) 储存 = .当前版本路径;
            if ((n.版本容器块种类 & (版本容器块种类_.是版本容器块_ | 版本容器块种类_.是版本另如容器块_ | 版本容器块种类_.是版本否则容器块_)) != 0) {
                .当前版本路径 = .转为单维去重数组((cast(块_)(node)).版本语句路径);
            }
            .优先绑定函数声明(node);
            .当前的外部修饰符 = 储存当前的外部修饰符;
            .声明块符号标志组 = 储存声明块符号标志组;
            .当前版本路径 = 储存;
            break;
        }
        default: {
            .绑定每个子节点(node);
        }
    }
}
核心.词典_!(核心.去重数组_!(dstring)) 转换为去重数组(核心.词典_!(dstring) 词典) {
    核心.词典_!(核心.去重数组_!(dstring)) 新词典 = new 核心.词典_!(核心.去重数组_!(dstring))();
    词典.p·循环每个((dstring v, dstring k) {
        核心.去重数组_!(dstring) 目标 = new 核心.去重数组_!(dstring)();
        目标.p·设置(v);
        新词典.p·设置(k, 目标);
    });
    return 新词典;
}
核心.词典_!(dstring) 转为文本词典(核心.词典_!(核心.去重数组_!(dstring)) 词典) {
    核心.词典_!(dstring) 新词典 = new 核心.词典_!(dstring)();
    词典.p·循环每个((去重数组_!(dstring) v, dstring k) {
        新词典.p·设置(k, v.去重排序输出());
    });
    return 新词典;
}
核心.去重数组_!(dstring) 转为单维去重数组(核心.去重数组_!(dstring)[] 数组 = ··null!(核心.去重数组_!(dstring)[])) {
    核心.去重数组_!(dstring) 目标 = new 核心.去重数组_!(dstring)();
    if (数组 is ··null!(核心.去重数组_!(dstring)[])) {
        return 目标;
    }
    foreach (核心.去重数组_!(dstring) s; 数组) {
        目标.p·合并(s);
    }
    return 目标;
}
void 绑定版本表达式语句(版本表达式语句_ node) {
    dstring 标识符 = 核心.文本转大写(node.表达式.标识符.内容);
    核心.去重数组_!(dstring) 是否为原来的 = 文件设置的版本标识符.获取(标识符);
    if (是否为原来的.去重排序输出() != 标识符) {
        .error(node.表达式, 诊断集_.重复的版本定义_0, 标识符);
    }
    文件设置的版本标识符.p·设置(标识符, .当前版本路径);
    .绑定每个子节点(node);
}
核心.去重数组_!(dstring) 计算版本表达式(节点_ node) {
    void delegate(节点_) 内部计算;
    bool 前缀;
    核心.去重数组_!(dstring) 数据;
    void 内部计算·func(节点_ n) {
        switch (n.目标种类) {
            case KSK.符号引用表达式: {
                内部计算((cast(符号引用表达式_)(n)).表达式);
                break;
            }
            case KSK.标识符: {
                dstring 标识符 = 核心.文本转大写((cast(标识符_)(n)).标识符.内容);
                if (文件设置的版本标识符.具有(标识符)) {
                    核心.去重数组_!(dstring) 可能是多个 = 文件设置的版本标识符.获取(标识符);
                    if ((可能是多个 is ··null!(核心.去重数组_!(dstring))) || 可能是多个.大小() == 0) {
                        break;
                    }
                    if (可能是多个.大小() == 1) {
                        dstring 最后一个 = 可能是多个.最后一个();
                        if (最后一个 == 标识符) {
                            .error(n, 诊断集_.在定义之前使用版本标识符_0, 标识符);
                            break;
                        }
                    }
                    foreach (dstring bk; 可能是多个.数据) {
                        dstring vv = bk[0 .. $-1];
                        dstring 符号 = 核心.结尾包含(bk, "+"d) ? "-"d : "+"d;
                        if (数据.p·具有(vv ~ 符号)) {
                            .error(n, 诊断集_.存在冲突的版本表达式_0, vv);
                        }
                    }
                    if (!前缀) {
                        可能是多个 = .数据取反(可能是多个);
                        数据.p·合并(可能是多个);
                    }
                    else {
                        数据.p·合并(可能是多个);
                    }
                }
                else {
                    dstring 符号 = 前缀 ? "+"d : "-"d;
                    dstring 值标识符 = 标识符 ~ 符号;
                    dstring 冲突 = 前缀 ? "-"d : "+"d;
                    if (数据.p·具有(标识符 ~ 冲突)) {
                        .error(n, 诊断集_.存在冲突的版本表达式_0, 标识符);
                    }
                    数据.p·设置(值标识符);
                }
                break;
            }
            case KSK.前缀一元表达式: {
                KSK 运算符 = (cast(前缀一元表达式_)(n)).运算符;
                if (运算符 != KSK.叹号) {
                    .error(n, 诊断集_.版本表达式只支持_0_运算符, "!"d);
                }
                else {
                    前缀 = 前缀 ? false : true;
                    内部计算((cast(前缀一元表达式_)(n)).表达式);
                    前缀 = 前缀 ? false : true;
                }
                break;
            }
            case KSK.二元表达式: {
                KSK 运算符 = (cast(二元表达式_)(n)).运算符;
                if (运算符 != KSK.且且号) {
                    .error(n, 诊断集_.版本表达式只支持_0_运算符, "&&"d);
                }
                else {
                    内部计算((cast(二元表达式_)(n)).左侧);
                    内部计算((cast(二元表达式_)(n)).右侧);
                }
                break;
            }
            default: {
                .error(n, 诊断集_.不可计算表达式);
                break;
            }
        }
    }
    内部计算 = &内部计算·func;
    前缀 = true;
    数据 = new 核心.去重数组_!(dstring)();
    内部计算(node);
    return 数据;
}
核心.去重数组_!(dstring) 数据取反(核心.去重数组_!(dstring) 数据) {
    dstring[] 数组 = 创建数组!(dstring)();
    foreach (dstring v; 数据.数据) {
        if (核心.结尾包含(v, "+"d)) {
            dstring vv = v[0 .. $-1];
            .追加!(dstring)(数组, vv ~ "-"d);
        }
        else {
            dstring vv = v[0 .. $-1];
            .追加!(dstring)(数组, vv ~ "+"d);
        }
    }
    数据.数据 = 数组;
    return 数据;
}
核心.去重数组_!(dstring)[] 复制版本语句路径(核心.去重数组_!(dstring)[] 路径 = ··null!(核心.去重数组_!(dstring)[])) {
    if (路径 is ··null!(核心.去重数组_!(dstring)[])) {
        return ··null!(核心.去重数组_!(dstring)[]);
    }
    核心.去重数组_!(dstring)[] 结果 = 创建数组!(核心.去重数组_!(dstring))();
    foreach (核心.去重数组_!(dstring) v; 路径) {
        核心.去重数组_!(dstring) 新路径 = new 核心.去重数组_!(dstring)();
        新路径.数据 = 克隆数组!(dstring)(v.数据);
        .追加!(核心.去重数组_!(dstring))(结果, 新路径);
    }
    return 结果;
}
void 追加入路径(ref 核心.去重数组_!(dstring)[] 路径, 核心.去重数组_!(dstring) 元素, 基础节点.节点_ 错误节点) {
    if (路径.length == 0) {
        .追加!(核心.去重数组_!(dstring))(路径, 元素);
    }
    else {
        foreach (核心.去重数组_!(dstring) ls; 路径) {
            if (ls.大小() == 1 && 元素.大小() == 1) {
                dstring zh1 = ls.最后一个();
                dstring zh2 = 元素.最后一个();
                dstring v1 = zh1[0 .. $-1];
                dstring v2 = zh2[0 .. $-1];
                if (v1 == v2) {
                    bool 是相反数据 = 核心.结尾包含(zh1, "-"d) ? 核心.结尾包含(zh2, "+"d) : 核心.结尾包含(zh2, "-"d);
                    if (是相反数据) {
                        .error(错误节点, 诊断集_.存在冲突的版本表达式_0, zh2);
                    }
                }
            }
            else if (ls.大小() <= 元素.大小()) {
                bool 冲突 = true;
                foreach (dstring l; ls.数据) {
                    bool 是减号 = 核心.结尾包含(l, "-"d);
                    dstring 存在 = 元素.p·查找(l);
                    if (存在 is ··null!(dstring)) {
                        dstring ll = l[0 .. $-1];
                        ll = 是减号 ? ll ~ "+"d : ll ~ "-"d;
                        存在 = 元素.p·查找(ll);
                        if (存在 is ··null!(dstring)) {
                            冲突 = false;
                            break;
                        }
                    }
                    bool 是相反数据 = 是减号 ? 核心.结尾包含(存在, "+"d) : 核心.结尾包含(存在, "-"d);
                    if (是相反数据) {
                        continue;
                    }
                    冲突 = false;
                    break;
                }
                if (冲突) {
                    .error(错误节点, 诊断集_.存在冲突的版本表达式_0, 元素.去重排序输出());
                }
            }
        }
        .追加!(核心.去重数组_!(dstring))(路径, 元素);
    }
}
核心.去重数组_!(dstring)[] 计算继承的版本路径(基础节点.节点_ node) {
    基础节点.节点_ 祖先块 = 查找祖先(node, (基础节点.节点_ n) {
        if (n.目标种类 == KSK.块 && ((cast(块_)(n)).版本容器块种类 & (版本容器块种类_.是测试单元_ | 版本容器块种类_.是版本容器块_ | 版本容器块种类_.是版本另如容器块_ | 版本容器块种类_.是版本否则容器块_)) != 0) {
            return 三元结果_.真_;
        }
        if ((n is ··null!(基础节点.节点_)) || n.目标种类 == KSK.源文件) {
            return 三元结果_.初始_;
        }
        return 三元结果_.假_;
    });
    核心.去重数组_!(dstring)[] 应该继承的;
    if (祖先块 !is ··null!(基础节点.节点_)) {
        if (祖先块.目标种类 == KSK.测试单元语句) {
            应该继承的 = .复制版本语句路径((cast(测试单元语句_)(祖先块)).版本语句路径);
        }
        else if (祖先块.目标种类 == KSK.导入成员块) {
            应该继承的 = .复制版本语句路径((cast(导入成员块_)(祖先块)).版本语句路径);
        }
        else if (祖先块.目标种类 == KSK.导入从成员块) {
            应该继承的 = .复制版本语句路径((cast(导入从成员块_)(祖先块)).版本语句路径);
        }
        else if (祖先块.目标种类 == KSK.块) {
            应该继承的 = .复制版本语句路径((cast(块_)(祖先块)).版本语句路径);
        }
    }
    if (应该继承的 is ··null!(核心.去重数组_!(dstring)[])) {
        应该继承的 = 创建数组!(核心.去重数组_!(dstring))();
    }
    return 应该继承的;
}
void 绑定版本语句(版本语句_ node) {
    块_ 然后语句 = node.然后语句;
    if (node.父节点.目标种类 == KSK.版本语句 && node == (cast(版本语句_)(node.父节点)).否则语句) {
        块_ 父然后语句 = (cast(块_)((cast(版本语句_)(node.父节点)).然后语句));
        然后语句.版本语句路径 = .计算版本语句路径(node.表达式, 父然后语句.版本语句路径);
    }
    else {
        核心.去重数组_!(dstring) 标识符 = .计算版本表达式(node.表达式);
        核心.去重数组_!(dstring)[] 应该继承的 = .计算继承的版本路径(node);
        if (!标识符.是空的()) {
            .追加入路径(应该继承的, 标识符, node.表达式);
        }
        if (应该继承的.length > 0) {
            然后语句.版本语句路径 = 应该继承的;
        }
    }
    节点_ 否则语句 = node.否则语句;
    if ((否则语句 !is ··null!(节点_)) && 否则语句.目标种类 == KSK.块) {
        (cast(块_)(否则语句)).版本语句路径 = .计算版本语句路径(node.表达式, 然后语句.版本语句路径, true);
    }
    .绑定每个子节点(node);
}
核心.去重数组_!(dstring)[] 计算版本语句路径(节点_ 表达式, 核心.去重数组_!(dstring)[] 版本语句路径 = ··null!(核心.去重数组_!(dstring)[]), bool 需要取反 = false) {
    核心.去重数组_!(dstring)[] 路径 = .复制版本语句路径(版本语句路径);
    if (路径 is ··null!(核心.去重数组_!(dstring)[])) {
        return ··null!(核心.去重数组_!(dstring)[]);
    }
    核心.去重数组_!(dstring) 标识符 = .计算版本表达式(表达式);
    核心.去重数组_!(dstring) 最后一个 = 路径[路径.length - 1];
    核心.去重数组_!(dstring) 新的最后一个 = .数据取反(最后一个);
    路径.length = 路径.length - 1;
    .追加入路径(路径, 新的最后一个, 表达式);
    if (!标识符.是空的()) {
        .追加入路径(路径, 需要取反 ? .数据取反(标识符) : 标识符, 表达式);
    }
    return 路径;
}
void 绑定导入版本成员(导入版本成员_ node) {
    导入成员块_ 然后语句 = node.然后语句;
    if (node.父节点.目标种类 == KSK.导入版本成员 && node == (cast(导入版本成员_)(node.父节点)).否则语句) {
        导入成员块_ 父然后语句 = (cast(导入版本成员_)(node.父节点)).然后语句;
        然后语句.版本语句路径 = .计算版本语句路径(node.表达式, 父然后语句.版本语句路径);
    }
    else {
        核心.去重数组_!(dstring) 标识符 = .计算版本表达式(node.表达式);
        核心.去重数组_!(dstring)[] 应该继承的 = .计算继承的版本路径(node);
        if (!标识符.是空的()) {
            .追加入路径(应该继承的, 标识符, node.表达式);
        }
        if (应该继承的.length > 0) {
            然后语句.版本语句路径 = 应该继承的;
        }
    }
    ··Klang节点_.导入成员基类_ 否则语句 = node.否则语句;
    if ((否则语句 !is ··null!(··Klang节点_.导入成员基类_)) && 否则语句.目标种类 == KSK.导入从成员块) {
        (cast(导入成员块_)(否则语句)).版本语句路径 = .计算版本语句路径(node.表达式, 然后语句.版本语句路径, true);
    }
    .绑定每个子节点(node);
}
void 绑定导入从版本成员(导入从版本成员_ node) {
    导入从成员块_ 然后语句 = node.然后语句;
    if (node.父节点.目标种类 == KSK.导入从版本成员 && node == (cast(导入从版本成员_)(node.父节点)).否则语句) {
        导入从成员块_ 父然后语句 = (cast(导入从版本成员_)(node.父节点)).然后语句;
        然后语句.版本语句路径 = .计算版本语句路径(node.表达式, 父然后语句.版本语句路径);
    }
    else {
        核心.去重数组_!(dstring) 标识符 = .计算版本表达式(node.表达式);
        核心.去重数组_!(dstring)[] 应该继承的 = .计算继承的版本路径(node);
        if (!标识符.是空的()) {
            .追加入路径(应该继承的, 标识符, node.表达式);
        }
        if (应该继承的.length > 0) {
            然后语句.版本语句路径 = 应该继承的;
        }
    }
    ··Klang节点_.导入从成员基类_ 否则语句 = node.否则语句;
    if ((否则语句 !is ··null!(··Klang节点_.导入从成员基类_)) && 否则语句.目标种类 == KSK.导入从成员块) {
        (cast(导入从成员块_)(否则语句)).版本语句路径 = .计算版本语句路径(node.表达式, 然后语句.版本语句路径, true);
    }
    .绑定每个子节点(node);
}
void 绑定测试单元语句(测试单元语句_ node) {
    核心.去重数组_!(dstring)[] 应该继承的 = .计算继承的版本路径(node);
    核心.去重数组_!(dstring) 标识符 = new 核心.去重数组_!(dstring)();
    标识符.p·设置("测试+"d);
    .追加!(核心.去重数组_!(dstring))(应该继承的, 标识符);
    node.版本语句路径 = 应该继承的;
    核心.去重数组_!(dstring) 储存 = .当前版本路径;
    .当前版本路径 = .转为单维去重数组(node.版本语句路径);
    .绑定每个子节点(node);
    .当前版本路径 = 储存;
}
void 绑定调用表达式(调用表达式_ node) {
    节点_ expr = node.表达式;
    if (expr.目标种类 == KSK.函数表达式 || expr.目标种类 == KSK.箭头函数) {
        .绑定每个成员(·to!(节点数组_!(基础节点.节点_))(node.类型实参组));
        .绑定每个成员(·to!(节点数组_!(基础节点.节点_))(node.实参组));
        .绑定函数(node.表达式);
    }
    else {
        .绑定每个子节点(node);
    }
}
void bindLogicalExpression(二元表达式_ node, 流节点_ trueTarget, 流节点_ falseTarget) {
    流节点_ preRightLabel = .createBranchLabel();
    if (node.运算符 == KSK.且且号) {
        .bindCondition(node.左侧, preRightLabel, falseTarget);
    }
    else {
        .bindCondition(node.左侧, trueTarget, preRightLabel);
    }
    .currentFlow = .finishFlowLabel(preRightLabel);
    .bindCondition(node.右侧, trueTarget, falseTarget);
}
void 绑定前缀一元表达式(前缀一元表达式_ node) {
    if (node.运算符 == KSK.叹号) {
        流节点_ saveTrueTarget = .currentTrueTarget;
        .currentTrueTarget = .currentFalseTarget;
        .currentFalseTarget = saveTrueTarget;
        .绑定每个子节点(node);
        .currentFalseTarget = .currentTrueTarget;
        .currentTrueTarget = saveTrueTarget;
    }
    else {
        .绑定每个子节点(node);
        if (node.运算符 == KSK.加加号 || node.运算符 == KSK.减减号) {
            .bindAssignmentTargetFlow(node.表达式);
        }
    }
}
bool isTopLevelLogicalExpression(基础节点.节点_ node) {
    while(node.父节点.目标种类 == KSK.前缀一元表达式 && (cast(前缀一元表达式_)(node.父节点)).运算符 == KSK.叹号) {
        node = node.父节点;
    }
    return !.是语句里的条件(node) && !.是逻辑表达式(node.父节点);
}
bool 是语句里的条件(基础节点.节点_ node) {
    基础节点.节点_ parent = node.父节点;
    switch (parent.目标种类) {
        case KSK.如果语句: {
            return (cast(如果语句_)(parent)).表达式 == node;
        }
        case KSK.当循环语句: {
            return (cast(当循环语句_)(parent)).表达式 == node;
        }
        case KSK.循环语句: {
            return (cast(循环语句_)(parent)).条件 == node;
        }
        case KSK.条件表达式: {
            return (cast(条件表达式_)(parent)).条件 == node;
        }
        default: break;
    }
    return false;
}
void 绑定后缀一元表达式(后缀一元表达式_ node) {
    .绑定每个子节点(node);
    if (node.运算符 == KSK.加加号 || node.运算符 == KSK.减减号) {
        .bindAssignmentTargetFlow(node.表达式);
    }
}
void 绑定二元表达式(二元表达式_ node) {
    KSK operator = node.运算符;
    if (operator == KSK.且且号 || operator == KSK.或或号) {
        if (.isTopLevelLogicalExpression(node)) {
            流节点_ postExpressionLabel = .createBranchLabel();
            .bindLogicalExpression(node, postExpressionLabel, postExpressionLabel);
            .currentFlow = .finishFlowLabel(postExpressionLabel);
        }
        else {
            .bindLogicalExpression(node, .currentTrueTarget, .currentFalseTarget);
        }
    }
    else {
        .绑定每个子节点(node);
        if (isAssignmentOperator(operator) && !是赋值目标(node)) {
            .bindAssignmentTargetFlow(node.左侧);
            if (operator == KSK.等号 && node.左侧.目标种类 == KSK.元素访问表达式) {
                元素访问表达式_ elementAccess = (cast(元素访问表达式_)(node.左侧));
                if (.是可收窄算子(elementAccess.表达式)) {
                    .currentFlow = .createFlowArrayMutation(.currentFlow, node);
                }
            }
        }
    }
}
void 绑定条件表达式(条件表达式_ node) {
    流节点_ trueLabel = .createBranchLabel();
    流节点_ falseLabel = .createBranchLabel();
    流节点_ postExpressionLabel = .createBranchLabel();
    .bindCondition(node.条件, trueLabel, falseLabel);
    .currentFlow = .finishFlowLabel(trueLabel);
    .绑定函数(node.当真);
    .addAntecedent(postExpressionLabel, .currentFlow);
    .currentFlow = .finishFlowLabel(falseLabel);
    .绑定函数(node.当假);
    .addAntecedent(postExpressionLabel, .currentFlow);
    .currentFlow = .finishFlowLabel(postExpressionLabel);
}
void 绑定假如语句(假如语句_ node) {
    流节点_ postSwitchLabel = .createBranchLabel();
    .绑定函数(node.表达式);
    流节点_ saveBreakTarget = .currentBreakTarget;
    流节点_ savePreSwitchCaseFlow = .preSwitchCaseFlow;
    .currentBreakTarget = postSwitchLabel;
    .preSwitchCaseFlow = .currentFlow;
    .绑定函数(node.若是块);
    .addAntecedent(postSwitchLabel, .currentFlow);
    bool hasDefault = 循环每个!(若是或默认子句_, bool)(node.若是块.子句组, (若是或默认子句_ c, size_t _) { return c.目标种类 == KSK.默认子句; });
    node.possiblyExhaustive = !hasDefault && (postSwitchLabel.antecedents is ··null!(流节点_[]));
    if (!hasDefault) {
        .addAntecedent(postSwitchLabel, .createFlowSwitchClause(.preSwitchCaseFlow, node, 0, 0));
    }
    .currentBreakTarget = saveBreakTarget;
    .preSwitchCaseFlow = savePreSwitchCaseFlow;
    .currentFlow = .finishFlowLabel(postSwitchLabel);
}
void 绑定标签语句(标签语句_ node) {
    流节点_ preStatementLabel = .createLoopLabel();
    流节点_ postStatementLabel = .createBranchLabel();
    .绑定函数(node.标签);
    .addAntecedent(preStatementLabel, .currentFlow);
    活动标签_ activeLabel = .pushActiveLabel(node.标签.标识符.内容, postStatementLabel, preStatementLabel, node);
    .绑定函数(node.语句);
    .popActiveLabel();
    if (!activeLabel.referenced) {
        .error(node.标签, 诊断集_.Unused_label);
    }
    if (node.语句 is ··null!(节点_)) {
        // do statement sets current flow inside bindDoStatement
        .addAntecedent(postStatementLabel, .currentFlow);
        .currentFlow = .finishFlowLabel(postStatementLabel);
    }
}
void 绑定若是块(若是块_ node) {
    节点数组_!(若是或默认子句_) clauses = node.子句组;
    流节点_ fallthroughFlow = .unreachableFlow;
    {
        for (int i = 0; i < clauses.length; ++i) {
            int clauseStart = i;
            while(clauses[i].语句组.length == 0 && i + 1 < clauses.length) {
                .绑定函数(clauses[i]);
                ++i;
            }
            流节点_ preCaseLabel = .createBranchLabel();
            .addAntecedent(preCaseLabel, .createFlowSwitchClause(.preSwitchCaseFlow, (cast(假如语句_)(node.父节点)), clauseStart, i + 1));
            .addAntecedent(preCaseLabel, fallthroughFlow);
            .currentFlow = .finishFlowLabel(preCaseLabel);
            若是或默认子句_ clause = clauses[i];
            .绑定函数(clause);
            fallthroughFlow = .currentFlow;
            if ((currentFlow.标志 & 流标志_.Unreachable) == 0 && i != clauses.length - 1) {
                clause.fallthroughFlowNode = .currentFlow;
            }
        }
    }
}
void 绑定若是子句(若是子句_ node) {
    流节点_ saveCurrentFlow = .currentFlow;
    .currentFlow = .preSwitchCaseFlow;
    .绑定函数(node.表达式);
    .currentFlow = saveCurrentFlow;
    .绑定每个成员(·to!(节点数组_!(基础节点.节点_))(node.语句组));
}
void 绑定变量声明流(变量声明_ node) {
    .绑定每个子节点(node);
    if (node.初始化 !is ··null!(节点_)) {
        .currentFlow = .createFlowMutation(流标志_.Assignment, .currentFlow, node);
    }
}
void 绑定尝试语句(尝试语句_ node) {
    流节点_ saveReturnTarget = .currentReturnTarget;
    流节点_ saveExceptionTarget = .currentExceptionTarget;
    流节点_ normalExitLabel = .createBranchLabel();
    流节点_ returnLabel = .createBranchLabel();
    流节点_ exceptionLabel = .createBranchLabel();
    if (node.最后块 !is ··null!(块_)) {
        .currentReturnTarget = returnLabel;
    }
    .addAntecedent(exceptionLabel, .currentFlow);
    .currentExceptionTarget = exceptionLabel;
    .绑定函数(node.尝试块);
    .addAntecedent(normalExitLabel, .currentFlow);
    if (node.捕获子句 !is ··null!(··Klang节点_.捕获子句_)) {
        .currentFlow = .finishFlowLabel(exceptionLabel);
        exceptionLabel = .createBranchLabel();
        .addAntecedent(exceptionLabel, .currentFlow);
        .currentExceptionTarget = exceptionLabel;
        .绑定函数(node.捕获子句);
        .addAntecedent(normalExitLabel, .currentFlow);
    }
    .currentReturnTarget = saveReturnTarget;
    .currentExceptionTarget = saveExceptionTarget;
    if (node.最后块 !is ··null!(块_)) {
        流节点_ finallyLabel = .createBranchLabel();
        流节点_[] antecedents = (cast(流节点_[])([]));
        if (normalExitLabel.antecedents !is ··null!(流节点_[])) {
            .追加!(流节点_)(antecedents, normalExitLabel.antecedents);
        }
        if (exceptionLabel.antecedents !is ··null!(流节点_[])) {
            .追加!(流节点_)(antecedents, exceptionLabel.antecedents);
        }
        if (returnLabel.antecedents !is ··null!(流节点_[])) {
            .追加!(流节点_)(antecedents, returnLabel.antecedents);
        }
        finallyLabel.antecedents = antecedents;
        if ((currentFlow.标志 & 流标志_.Unreachable) != 0) {
            // If the end of the finally block is unreachable, the end of the entire try statement is unreachable.
            .currentFlow = .unreachableFlow;
        }
        else {
            // If we have an IIFE return target and return statements in the try or catch blocks, add a control
            // flow that goes back through the finally block and back through only the return statements.
            if ((.currentReturnTarget !is ··null!(流节点_)) && (returnLabel.antecedents !is ··null!(流节点_[]))) {
                .addAntecedent(.currentReturnTarget, .createReduceLabel(finallyLabel, returnLabel.antecedents, .currentFlow));
            }
            // If we have an outer exception target (i.e. a containing try-finally or try-catch-finally), add a
            // control flow that goes back through the finally blok and back through each possible exception source.
            if ((.currentExceptionTarget !is ··null!(流节点_)) && (exceptionLabel.antecedents !is ··null!(流节点_[]))) {
                .addAntecedent(.currentExceptionTarget, .createReduceLabel(finallyLabel, exceptionLabel.antecedents, .currentFlow));
            }
            // If the end of the finally block is reachable, but the end of the try and catch blocks are not,
            // convert the current flow to unreachable. For example, 'try { return 1; } finally { ... }' should
            // result in an unreachable current control flow.
            .currentFlow = normalExitLabel.antecedents ? .createReduceLabel(finallyLabel, normalExitLabel.antecedents, .currentFlow) : .unreachableFlow;
        }
    }
    else {
        .currentFlow = .finishFlowLabel(normalExitLabel);
    }
}
活动标签_ findActiveLabel(dstring name) {
    if (.activeLabels !is ··null!(活动标签_[])) {
        foreach (活动标签_ label; .activeLabels) {
            if (label.name == name) {
                return label;
            }
        }
    }
    return ··null!(活动标签_);
}
活动标签_ pushActiveLabel(dstring name, 流节点_ breakTarget, 流节点_ continueTarget, 标签语句_ node) {
    活动标签_ activeLabel = new 活动标签_(node, name, breakTarget, continueTarget, false);
    if (.activeLabels is ··null!(活动标签_[])) {
        .activeLabels = 创建数组!(活动标签_)();
    }
    .追加!(活动标签_)(.activeLabels, activeLabel);
    return activeLabel;
}
void popActiveLabel() {
    .activeLabels = activeLabels[0 .. $-1];
}
void bindBreakOrContinueFlow(节点_ node, 流节点_ breakTarget = ··null!(流节点_), 流节点_ continueTarget = ··null!(流节点_)) {
    流节点_ flowLabel = node.目标种类 == KSK.跳出语句 ? breakTarget : continueTarget;
    if (flowLabel !is ··null!(流节点_)) {
        .addAntecedent(flowLabel, .currentFlow);
        .currentFlow = .unreachableFlow;
    }
}
void 绑定跳出语句(跳出语句_ node) {
    .绑定函数(node.标签);
    if (node.标签 !is ··null!(标识符_)) {
        活动标签_ activeLabel = .findActiveLabel(node.标签.标识符.内容);
        if (activeLabel !is ··null!(活动标签_)) {
            activeLabel.referenced = true;
            .bindBreakOrContinueFlow(node, activeLabel.breakTarget, activeLabel.continueTarget);
        }
    }
    else {
        .bindBreakOrContinueFlow(node, .currentBreakTarget, .currentContinueTarget);
    }
}
void 绑定继续语句(继续语句_ node) {
    .绑定函数(node.标签);
    if (node.标签 !is ··null!(标识符_)) {
        活动标签_ activeLabel = .findActiveLabel(node.标签.标识符.内容);
        if (activeLabel !is ··null!(活动标签_)) {
            activeLabel.referenced = true;
            .bindBreakOrContinueFlow(node, activeLabel.breakTarget, activeLabel.continueTarget);
        }
    }
    else {
        .bindBreakOrContinueFlow(node, .currentBreakTarget, .currentContinueTarget);
    }
}
基础节点.节点_ 查找父函数(基础节点.节点_ node) {
    基础节点.节点_ 祖先函数 = 查找祖先(node, (基础节点.节点_ n) {
        if (是函数类的((cast(节点_)(n)))) {
            return 三元结果_.真_;
        }
        if ((n is ··null!(基础节点.节点_)) || n.目标种类 == KSK.程序声明 || n.目标种类 == KSK.源文件) {
            return 三元结果_.初始_;
        }
        return 三元结果_.假_;
    });
    return 祖先函数;
}
void 绑定返回语句(返回语句_ node) {
    .绑定函数(node.表达式);
    .hasExplicitReturn = true;
    if ((node.标志 & 节点标志_.是静态的_) != 0) {
        基础节点.节点_ fn = .查找父函数(node);
        if (fn !is ··null!(基础节点.节点_)) {
            fn.标志 |= (cast(整数_)(节点标志_.是静态的_));
        }
    }
    if (.currentReturnTarget !is ··null!(流节点_)) {
        .addAntecedent(.currentReturnTarget, .currentFlow);
    }
    .currentFlow = .unreachableFlow;
}
void 绑定抛出语句(抛出语句_ node) {
    .绑定函数(node.表达式);
    .currentFlow = .unreachableFlow;
}
void 处理条件分支(基础节点.节点_ value = ··null!(基础节点.节点_), 流节点_ trueTarget = ··null!(流节点_), 流节点_ falseTarget = ··null!(流节点_)) {
    流节点_ savedTrueTarget = .currentTrueTarget;
    流节点_ savedFalseTarget = .currentFalseTarget;
    .currentTrueTarget = trueTarget;
    .currentFalseTarget = falseTarget;
    .绑定函数(value);
    .currentTrueTarget = savedTrueTarget;
    .currentFalseTarget = savedFalseTarget;
}
bool 是逻辑表达式(基础节点.节点_ node) {
    while(true) {
        if (node.目标种类 == KSK.前缀一元表达式 && (cast(前缀一元表达式_)(node)).运算符 == KSK.叹号) {
            node = (cast(前缀一元表达式_)(node)).表达式;
        }
        else {
            return node.目标种类 == KSK.二元表达式 && ((cast(二元表达式_)(node)).运算符 == KSK.且且号 || (cast(二元表达式_)(node)).运算符 == KSK.或或号);
        }
    }
}
流节点_ createFlowCondition(流标志_ flags, 流节点_ antecedent, 基础节点.节点_ 表达式 = ··null!(基础节点.节点_)) {
    if ((antecedent.标志 & 流标志_.Unreachable) != 0) {
        return antecedent;
    }
    if (表达式 is ··null!(基础节点.节点_)) {
        return (flags & 流标志_.TrueCondition) != 0 ? antecedent : .unreachableFlow;
    }
    if (表达式.目标种类 == KSK.真_ && (flags & 流标志_.FalseCondition) != 0 || 表达式.目标种类 == KSK.假_ && (flags & 流标志_.TrueCondition) != 0) {
        return .unreachableFlow;
    }
    if (!.是可收窄表达式((cast(节点_)(表达式)))) {
        return antecedent;
    }
    .setFlowNodeReferenced(antecedent);
    流节点_ 流 = new 流节点_(flags);
    流.antecedent = antecedent;
    流.node = 表达式;
    return .flowNodeCreated(流);
}
void bindCondition(基础节点.节点_ node = ··null!(基础节点.节点_), 流节点_ trueTarget = ··null!(流节点_), 流节点_ falseTarget = ··null!(流节点_)) {
    .处理条件分支(node, trueTarget, falseTarget);
    if ((node is ··null!(基础节点.节点_)) || !.是逻辑表达式(node)) {
        .addAntecedent(trueTarget, .createFlowCondition(流标志_.TrueCondition, .currentFlow, node));
        .addAntecedent(falseTarget, .createFlowCondition(流标志_.FalseCondition, .currentFlow, node));
    }
}
void 绑定当循环语句(当循环语句_ node) {
    流节点_ preWhileLabel = .createLoopLabel();
    流节点_ preBodyLabel = .createBranchLabel();
    流节点_ postWhileLabel = .createBranchLabel();
    .addAntecedent(preWhileLabel, .currentFlow);
    .currentFlow = preWhileLabel;
    .bindCondition(node.表达式, preBodyLabel, postWhileLabel);
    .currentFlow = .finishFlowLabel(preBodyLabel);
    .bindIterativeStatement(node.语句, postWhileLabel, preWhileLabel);
    .addAntecedent(preWhileLabel, .currentFlow);
    .currentFlow = .finishFlowLabel(postWhileLabel);
}
void bindForStatement(循环语句_ node) {
    流节点_ preLoopLabel = .createLoopLabel();
    流节点_ preBodyLabel = .createBranchLabel();
    流节点_ postLoopLabel = .createBranchLabel();
    .绑定函数(node.初始化);
    .addAntecedent(preLoopLabel, .currentFlow);
    .currentFlow = preLoopLabel;
    .bindCondition(node.条件, preBodyLabel, postLoopLabel);
    .currentFlow = .finishFlowLabel(preBodyLabel);
    .bindIterativeStatement(node.语句, postLoopLabel, preLoopLabel);
    .绑定函数(node.自增);
    .addAntecedent(preLoopLabel, .currentFlow);
    .currentFlow = .finishFlowLabel(postLoopLabel);
}
void bindForInOrForOfStatement(循环属于_ node) {
    流节点_ preLoopLabel = .createLoopLabel();
    流节点_ postLoopLabel = .createBranchLabel();
    .绑定函数(node.表达式);
    .addAntecedent(preLoopLabel, .currentFlow);
    .currentFlow = preLoopLabel;
    .addAntecedent(postLoopLabel, .currentFlow);
    .绑定函数(node.初始化);
    if (node.初始化.目标种类 != KSK.变量声明列表) {
        .bindAssignmentTargetFlow(node.初始化);
    }
    .bindIterativeStatement(node.语句, postLoopLabel, preLoopLabel);
    .addAntecedent(preLoopLabel, .currentFlow);
    .currentFlow = .finishFlowLabel(postLoopLabel);
}
void bindAssignmentTargetFlow(节点_ node) {
    if (.是可收窄引用(node)) {
        .currentFlow = .createFlowMutation(流标志_.Assignment, .currentFlow, node);
    }
    else if (node.目标种类 == KSK.数组字面量表达式) {
        foreach (节点_ e; ((cast(数组字面量表达式_)(node)).元素组)) {
            if (e.目标种类 == KSK.展开表达式) {
                .bindAssignmentTargetFlow((cast(展开表达式_)(e)).表达式);
            }
            else {
                .bindDestructuringTargetFlow(e);
            }
        }
    }
    else if (node.目标种类 == KSK.动态类字面量表达式) {
        foreach (节点_ e; (cast(动态类字面量表达式_)(node)).元素组) {
            if (e.目标种类 == KSK.展开表达式) {
                .bindAssignmentTargetFlow((cast(展开表达式_)(e)).表达式);
            }
            else {
                .bindDestructuringTargetFlow(e);
            }
        }
    }
    else if (node.目标种类 == KSK.表达式列表表达式) {
        foreach (节点_ e; (cast(表达式列表表达式_)(node)).元素组) {
            if (e.目标种类 == KSK.展开表达式) {
                .bindAssignmentTargetFlow((cast(展开表达式_)(e)).表达式);
            }
            else {
                .bindDestructuringTargetFlow(e);
            }
        }
    }
    else if (node.目标种类 == KSK.结构字面量表达式) {
        foreach (节点_ p; (cast(结构字面量表达式_)(node)).属性组) {
            if (p.目标种类 == KSK.属性赋值) {
                属性赋值_ np = (cast(属性赋值_)(p));
                .bindDestructuringTargetFlow(np.初始化);
            }
            else if (p.目标种类 == KSK.简洁属性赋值) {
                简洁属性赋值_ np = (cast(简洁属性赋值_)(p));
                .bindAssignmentTargetFlow(np.名称);
            }
            else if (p.目标种类 == KSK.展开表达式) {
                展开表达式_ np = (cast(展开表达式_)(p));
                .bindAssignmentTargetFlow(np.表达式);
            }
        }
    }
    else if (node.目标种类 == KSK.接口字面量表达式) {
        foreach (节点_ p; (cast(接口字面量表达式_)(node)).属性组) {
            if (p.目标种类 == KSK.属性赋值) {
                属性赋值_ np = (cast(属性赋值_)(p));
                .bindDestructuringTargetFlow(np.初始化);
            }
            else if (p.目标种类 == KSK.简洁属性赋值) {
                简洁属性赋值_ np = (cast(简洁属性赋值_)(p));
                .bindAssignmentTargetFlow(np.名称);
            }
        }
    }
    else if (node.目标种类 == KSK.词典键值表达式) {
        词典键值表达式_ n = (cast(词典键值表达式_)(node));
        .bindAssignmentTargetFlow(n.键表达式);
        .bindAssignmentTargetFlow(n.值表达式);
    }
}
void bindDestructuringTargetFlow(节点_ node) {
    if (node.目标种类 == KSK.二元表达式 && (cast(二元表达式_)(node)).运算符 == KSK.等号) {
        .bindAssignmentTargetFlow((cast(二元表达式_)(node)).左侧);
    }
    else {
        .bindAssignmentTargetFlow(node);
    }
}
void bindIterativeStatement(节点_ node, 流节点_ breakTarget, 流节点_ continueTarget) {
    流节点_ saveBreakTarget = .currentBreakTarget;
    流节点_ saveContinueTarget = .currentContinueTarget;
    .currentBreakTarget = breakTarget;
    .currentContinueTarget = continueTarget;
    .绑定函数(node);
    .currentBreakTarget = saveBreakTarget;
    .currentContinueTarget = saveContinueTarget;
}
void 绑定如果语句(如果语句_ n) {
    流节点_ thenLabel = .createBranchLabel();
    流节点_ elseLabel = .createBranchLabel();
    流节点_ postIfLabel = .createBranchLabel();
    .bindCondition(n.表达式, thenLabel, elseLabel);
    .currentFlow = .finishFlowLabel(thenLabel);
    .绑定函数(n.然后语句);
    .addAntecedent(postIfLabel, .currentFlow);
    .currentFlow = .finishFlowLabel(elseLabel);
    .绑定函数(n.否则语句);
    .addAntecedent(postIfLabel, .currentFlow);
    .currentFlow = .finishFlowLabel(postIfLabel);
}
void 绑定断言语句(断言语句_ node) {
    节点数组_!(节点_) 实参组 = node.实参组;
    if ((实参组 is null) || (实参组.原型 is ··null!(节点_[])) || 实参组.length != 2) {
        .绑定每个子节点(node);
        return;
    }
    节点_ 实参0 = 实参组[0];
    节点_ 实参1 = 实参组[1];
    流节点_ trueLabel = .createBranchLabel();
    流节点_ falseLabel = .createBranchLabel();
    流节点_ postIfLabel = .createBranchLabel();
    .bindCondition(实参0, trueLabel, falseLabel);
    .currentFlow = .finishFlowLabel(falseLabel);
    .绑定函数(实参1);
    .currentFlow = .finishFlowLabel(trueLabel);
    .addAntecedent(postIfLabel, .currentFlow);
    .currentFlow = .finishFlowLabel(postIfLabel);
}
void bindExpressionStatement(表达式语句_ node) {
    .绑定函数(node.表达式);
    if (node.表达式.目标种类 == KSK.调用表达式) {
        调用表达式_ call = (cast(调用表达式_)(node.表达式));
        if (是点的名称(call.表达式)) {
            .currentFlow = .createFlowCall(.currentFlow, call);
        }
    }
}
bool checkUnreachable(基础节点.节点_ node) {
    if ((currentFlow.标志 & 流标志_.Unreachable) == 0) {
        return false;
    }
    if (.currentFlow == .unreachableFlow) {
        if ((node.父节点 !is ··null!(基础节点.节点_)) && node.父节点.目标种类 == KSK.断言语句) {
            节点数组_!(节点_) 实参组 = (cast(断言语句_)(node.父节点)).实参组;
            if ((实参组 is null) || (实参组.原型 is ··null!(节点_[])) || 实参组.length != 2) {
                return true;
            }
            return 实参组[1] == node;
        }
        bool reportError = 是语句但不是声明(node.目标种类) || node.目标种类 == KSK.对象声明 || node.目标种类 == KSK.结构声明 || node.目标种类 == KSK.类型声明;
        if (reportError) {
            .currentFlow = .reportedUnreachableFlow;
            .eachUnreachableRange((cast(节点_)(node)), cast(void delegate(节点_, 节点_))(·fd(&.报告错误)));
        }
    }
    return true;
}
void 报告错误(基础节点.节点_ start, 基础节点.节点_ end) {
    文本范围_ n = new 文本范围_();
    n.开始 = start.开始;
    n.结束 = end.结束;
    .error(n, 诊断集_.Unreachable_code_detected, ""d);
}
void error(文本范围_ node, 诊断消息_ message, dstring arg0 = ··null!(dstring), dstring arg1 = ··null!(dstring), dstring arg2 = ··null!(dstring)) {
    if (file.绑定诊断 is ··null!(诊断_[])) {
        file.绑定诊断 = 创建数组!(诊断_)();
    }
    ··诊断_.诊断包括位置_ 消息 = 创建文件诊断消息(.file, node.开始, node.结束 - node.开始, message, [arg0, arg1, arg2]);
    .追加!(诊断_)(file.绑定诊断, 消息);
}
void eachUnreachableRange(节点_ node, void delegate(节点_, 节点_) cb) {
    if (.isExecutableStatement(node) && 是块((cast(节点_)(node.父节点)))) {
        块_ bpn = (cast(块_)(node.父节点));
        节点数组_!(节点_) statements = bpn.语句组;
        if ((statements !is null) && (statements.原型 !is ··null!(节点_[]))) {
            节点_[] slice = sliceAfter!(节点_)(statements, node);
            getRangesWhere!(节点_)(slice, cast(bool delegate(节点_))(·fd(&.isExecutableStatement)), (整数_ start, 整数_ afterEnd) { return cb(slice[start], slice[afterEnd - 1]); });
        }
    }
    else {
        cb(node, node);
    }
}
// As opposed to a pure declaration like an `interface`
bool isExecutableStatement(节点_ s) {
    return !是函数声明(s) && !.isPurelyTypeDeclaration(s) && !是枚举声明(s);
}
bool isPurelyTypeDeclaration(基础节点.节点_ s) {
    switch (s.目标种类) {
        case KSK.接口声明:
        case KSK.对象声明:
        case KSK.结构声明:
        case KSK.类型声明:
        case KSK.别名声明:
        case KSK.枚举声明: {
            return true;
        }
        default: {
            return false;
        }
    }
}
void setParentPointers(基础节点.节点_ 父节点, 基础节点.节点_ 子节点) {
    子节点.父节点 = 父节点;
    遍历节点(子节点, (基础节点.节点_ 子) { .setParentPointers(子节点, 子); return false; }, ··null!(bool delegate(节点数组_!(基础节点.节点_))));
}
